为什么 ReactJS 处理单选“checked”属性与其他属性不同?

2024-01-11

tl;drReact 拒绝兑现checked={checkThisOption}在输入上,即使它尊重data-ischecked={checkThisOption}完全在同一组输入上。

我还没有在 jsfiddle 上完成这项工作,但我已经使用重现了这个问题这段代码 https://gist.github.com/tomprogers/54e70947c4b95b60a7aa.

长版

我有一个简单的 ReactJS 组件,它向用户显示单选按钮列表。用户应该能够选择收音机,然后按下按钮来确认他们的选择。

这是组件 def(注意:我使用的是 ES6 和 webpack):

import React from 'react';

class Widget extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            currentValue: null // tracks currently-selected choice, by its value
        };
    }

    onClickOptionRadio = (event) => {
        this.setState({
            currentValue: String(event.currentTarget.value)
        });
    }

    onConfirm = (event) => {
        if(!this.props.onChange) return;
        this.props.onChange(this.state.currentValue);
    };

    render() {
        let choices = this.props.choices;
        let currentValue = this.state.currentValue;

        return (
            <div className="Widget">
                <ol className="choices">
                    {
                        choices.map((choice, i) => {
                            // decide whether to mark radio as checked:
                            // - if no current choice, check first radios
                            // - otherwise, check radio matching current choice
                            let noCurrentChoice      = (currentValue === null);
                            let drawingFirstChoice   = (i === 0);
                            let thisChoiceIsSelected = (String(choice.value) === currentValue);
                            let checkThisOption      = thisChoiceIsSelected || (noCurrentChoice && drawingFirstChoice);

                            return (
                                <li key={i}>
                                    <input type="radio" name="choices"
                                        value={choice.value}
                                        onChange={this.onClickOptionRadio}
                                        checked={checkThisOption?'checked':''}
                                        data-ischecked={checkThisOption}
                                        />

                                    <label>{choice.label}</label>
                                    {' '}

                                    {checkThisOption ? 'CHECKED' : ''}
                                </li>
                            );
                        })
                    }
                </ol>

                <button onClick={this.onConfirm}>Confirm choice</button>

            </div>
        );
    }

}

export default Widget;

这是所属组件:

import React from 'react';
import Widget from 'components/widget';

class Owner extends React.Component {
    constructor(props) {
        super(props);
        this.state = {};
    }

    render() {
        let choices = [
            { value: 10, label: 'First' },
            { value: 20, label: 'Second' },
            { value: 30, label: 'Third' }
        ];

        return (
            <div className="Owner">

                <Widget
                    choices={choices}
                    />

            </div>
        );
    }

}

export default Owner;

这是它的实际动图:

请注意视频中的几件事:

  • 该逻辑显然适用于在初始渲染时检查第一个无线电
  • 当用户点击其他无线电时,它们不会被选中
  • 然而,该逻辑显然适用于识别选择了哪个项目,如margin-right: 2rem在应该检查的收音机上
  • 指示已选择哪个选项的文本自始至终都是准确的
  • 当我点击收音机时,componentWillUpdate方法仅针对 Widget 本身触发;它的祖先都没有更新

我认为这个演示证明这不是一个案例Widget实例被状态为空的另一个实例替换。事实上,当前的选择准确地反映了data- attr 在输入上以及纯文本,表明状态按预期持续存在。我确信这种不受欢迎的行为是设计使然,我想知道如何解决 React 应用于受控输入的表单相关属性的奇怪、异常的逻辑。

为什么我认为当前的行为是错误的?我不希望拥有组件知道每个单选按钮 - 所有者应该绑定到 Widget 的onChange做出最终选择后通知的方法。

这是一个简化的示例。真正的组件更复杂,但原理是相同的:就像日期选择组件可能有许多其所属组件不知道的内部状态一样(例如要显示什么时间尺度,要显示哪一年、哪一个月或哪一周)显示等),该组件也有一些有趣的内部状态,拥有组件没有业务管理。

据我所知,我做得完全正确。该组件通过以下方式发布其重要的状态更新onChange(event, newValue),应该绑定到哪个拥有组件。我认为 React 很明显deciding不更新checked这些输入上的 attr,即使它显然能够更新相同元素上的其他 attr 以响应相同的用户操作。

注意楼主不是现在聆听onChange,但这并不重要:即使所有者没有在听,子组件也应该能够管理其自己的内部状态。我拒绝这样的说法,即无线电状态不能准确,只是因为所有者没有提供currentValuevia props:Widget 可以在没有该 prop 的情况下直接管理和渲染其状态。 React 必须做一些特殊的事情来防止checked不按照适用的规则进行处理所有其他元素和属性。这是一个例外,我认为这是一个糟糕的例外。

最后,请注意,此问题似乎仅在该组件位于某个复合树深度以下时才会发生。当它是 Flux“页面”或 Redux“容器”中唯一的组件时,它的效果很好。当它嵌套得更深时,正如我所描述的那样,它会失败。我还没有想出一个简洁的方式来展示这一点。

任何建议表示赞赏。据我所知,React 违反了它自己规定的规则,我预计这种行为会阻碍构建其他围绕普通版本构建的有状态组件inputs.

Edit:我更正了生成的name无线电,并更新了演示以反映它。向所有开始追寻这些东西的人道歉。


我已将其编辑为不使用类属性 https://github.com/jeffmo/es-class-fields-and-static-properties,并且无法重现:

Code:

class Widget extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      currentValue: null // tracks currently-selected choice, by its value
    };
    this.onClickOptionRadio = this.onClickOptionRadio.bind(this)
    this.onConfirm = this.onConfirm.bind(this)
  }

  onClickOptionRadio (event) {
    this.setState({
      currentValue: String(event.currentTarget.value)
    });
  }

  onConfirm (event) {
    if(!this.props.onChange) return;
    this.props.onChange(this.state.currentValue);
  };

  render() {
    let choices = this.props.choices;
    let currentValue = this.state.currentValue;

    return (
      <div className="Widget">
      <ol className="choices">
      {
        choices.map((choice, i) => {
          // decide whether to mark radio as checked:
          // - if no current choice, check first radios
          // - otherwise, check radio matching current choice
          let noCurrentChoice      = (currentValue === null);
          let drawingFirstChoice   = (i === 0);
          let thisChoiceIsSelected = (String(choice.value) === currentValue);
          let checkThisOption      = thisChoiceIsSelected || (noCurrentChoice && drawingFirstChoice);

          return (
            <li key={i}>
            <input type="radio" name="choices"
            value={choice.value}
            onChange={this.onClickOptionRadio}
            checked={checkThisOption?'checked':''}
            data-ischecked={checkThisOption}
            />

            <label>{choice.label}</label>
            {' '}

            {checkThisOption ? 'CHECKED' : ''}
            </li>
          );
        })
      }
      </ol>

      <button onClick={this.onConfirm}>Confirm choice</button>

      </div>
    );
  }

}


class Owner extends React.Component {
  constructor(props) {
    super(props);
    this.state = {};
  }

  render() {
    let choices = [
      { value: 10, label: 'First' },
      { value: 20, label: 'Second' },
      { value: 30, label: 'Third' }
    ];

    return (
      <div className="Owner">

      <Widget
      choices={choices}
      />

      </div>
    );
  }

}

ReactDOM.render(
  <Owner />,
  document.getElementById('container')
);

我的浏览器是 Chrome 47。这是jsfiddle。 https://jsfiddle.net/vjv14ezy/

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么 ReactJS 处理单选“checked”属性与其他属性不同? 的相关文章

随机推荐

  • 获取给定周年、给定月份和给定周的开始和结束日期

    如何在 c 4 0 中获取给定年份 int 给定月份 int 和给定周 int example Year 2011 Month 07 week 04 的开始和结束日期 提前致谢 2011 年的开始日期为 07 月 该月的周数为 04 Goo
  • Segue 传递数据后如何重新加载 tableView 数据

    我有两个表视图 一种是用户单击的 另一种是显示数据的 当用户单击第一个表视图中的单元格时 将对我的 firebase 数据库进行查询 并将查询存储在数组中 然后我通过 segue 传递数据 我使用了属性观察器 因此我知道正在设置变量 通过使
  • Ruby 类实例变量与类变量

    I read Ruby 实例变量何时设置 https stackoverflow com questions 826734 when do ruby instance variables get set但何时使用类实例变量我有两种想法 类变
  • MVVM标准化

    有人在Silverlight 发布 http forums silverlight net forums t 159237 aspxMVVM 目前缺乏标准化 因此每个人都有自己的风格 这就是为什么我和 WPF Disciples 的一些人正
  • AutoEventWireup 和 base.OnLoad(e) 调用 Self 导致堆栈溢出

    使用VS2008 C 什么时候AutoEventWireup设置为 true 并在我调用的网络表单中base OnLoad e like protected void Page Load object sender EventArgs e
  • 将 bash 变量放入 zip 命令的文件名中

    在 bash 脚本中 如何使用变量来创建专门命名的压缩文件 例如 我想做这样的事情 VERSION STRING 1 7 3 zip r foo VERSION STRING foo 理想情况下我最终会得到一个名为foo 1 7 3 zip
  • Java ArrayList如何在开头添加元素

    我需要将元素添加到ArrayList队列无论如何 但是当我调用该函数来添加元素时 我希望它在数组的开头添加该元素 因此它具有最低的索引 并且如果数组有 10 个元素 则添加新元素会删除最旧的元素元素 索引最高的元素 有没有人有什么建议 Li
  • 如何删除 XMLDocument 中的特定属性?

    在我的 C 代码库中 我有一个XMLDocument形式 a b b a
  • Django模型-如何添加订单索引注释?

    如何在 django 中注释查询集 以添加表示排序结果中每行的索引 位置 的附加字段 我需要以有序的方式检索用户 并添加一个字段 该字段将指定订单中每个对象的绝对位置 这就是我的代码 users User objects all annot
  • 用户“NT AUTHORITY\NETWORK SERVICE”登录失败

    我已经为此苦苦挣扎了两天 但仍未接近解决方案 我至少读了20 30个帖子 但仍然无法解决这个问题 请帮帮我 我已禁用匿名身份验证 启用 asp net 模拟 我已经添加了
  • 将 StudlyCaps 字符串拆分为单词

    我需要找到一种方法 使用 php regex 将字符串 下面的示例 拆分为空格分隔的单词 以下是一些字符串示例和我的预期输出 SomeRANDOMString gt 一些随机字符串ANOTHERRandomString gt 另一个随机字符
  • UIWebView 中 iOS 中的点与 CSS 中的大小单位?

    当您将 HTML 加载到 iOS 中的 UIWebView 中时 如何在 CSS 中获取 iOS 点单位 也就是说 iOS 中的点单位是相对于显示屏尺寸的相对尺寸测量 如何在 CSS 中获得这些相对点单位 最初 我的程序中有一个错误 很长一
  • Select 或 create 语句中的数据库列[重复]

    这个问题在这里已经有答案了 可能的重复 PostgreSQL 选择查询中的最大列数是多少 https stackoverflow com questions 12606842 what is the maximum number of co
  • 如何使用 PHP 从 .dat 文件中检索单独的数据行?

    我无法理解如何从数据中检索单独的数据行 例如名字 年龄 出生年份 性别 dat使用 PHP 文件 我对网上读到的所有内容感到困惑 我需要从文本中取出每一行 dat文件并为每一行分配自己的 variable稍后用于打印 到目前为止我所拥有的
  • 自 2020-06 新版本以来,Eclipse PHP 垃圾邮件出现新警告

    我在 Eclipse 中开发一个 PHP 项目 在更新到最新版本 2020 06 之前 我曾经没有任何警告 自从我进行此更新以来 它向我发送了两个警告 首先是关于类文件 例如 MyClass inc php 中定义的 MyClass Ecl
  • 使用 ggplot2 对数正态刻度进行漂亮的刻度(动态而非手动)

    我正在尝试使用 ggplot2 创建具有对数正态 y 刻度的性能图表 不幸的是 我无法为基本绘图函数生成漂亮的刻度 这是我的例子 library ggplot2 library scales fix RNG set seed seed 1
  • RStudio 在多次调用 Rcpp 函数后崩溃

    我编写了一些 Rcpp 代码来查找两条分段线性曲线的交点 我以需要嵌套循环 检查所有段对 的天真的方式解决了这个问题 所以为了速度而转向 Rcpp 该问题在 示例 1 中进行了图示描述 https prezi com rwkji leuwd
  • 如何跟踪和防止在单独进程中运行的c3po出现死锁?

    我有一个非常简单的计算 可以生成字母矩阵 可以找到矩阵中的所有单词 单词中的字母是相邻的单元格 for int i 0 i lt 500 i System out println i Matrix matrix new Matrix 4 m
  • 如何在 Perl 中检查多个模式匹配

    有没有办法避免使用它进行多重模式检查 我可以撕掉数组中的所有模式并检查它是否与模式数组中的任何模式匹配吗 请考虑当我有超过 20 个模式字符串时的情况 if so mdb v daidir solver cache csrc csrc vm
  • 为什么 ReactJS 处理单选“checked”属性与其他属性不同?

    tl drReact 拒绝兑现checked checkThisOption 在输入上 即使它尊重data ischecked checkThisOption 完全在同一组输入上 我还没有在 jsfiddle 上完成这项工作 但我已经使用重