更改值后反应组件未更新

Posted

技术标签:

【中文标题】更改值后反应组件未更新【英文标题】:React Component Not Updating After Changing A Value 【发布时间】:2017-09-15 13:03:30 【问题描述】:

在 ReactJS 中,我正在编写一个无状态组件; 因为我已经阅读了避免不必要的状态是最佳实践。

该组件表示一个输入字段,当输入框包含一个值时执行一个函数。

    export const InputField = (props) => 
      
      const InputFieldContentsChanged = (event) => 
        props.onChange(event.target.value);
      ;

      return (
        <div data-component="input-field"
          className=(props.value !== "" ? "value": "")>
          <input type=props.type value=props.value onChange=InputFieldContentsChanged />
          <span className="bar"></span>
          <label>props.label</label>
        </div>
      );
    ;

    InputField.PropTypes = 
      type: PropTypes.oneOf([ "text", "password" ]).isRequired,
      label: PropTypes.string.isRequired,
      value: PropTypes.string,
      onChange: PropTypes.func.isRequired
    

现在, 我创建了另一个组件,它只是用于测试上述组件的示例。 如下所示:

    export const SampleComponent = (props) => 
      
      let componentUsername = "";
      
      const onUsernameChanged = (username) => 
        componentUsername = username;
      ;
      
      return (
        <InputField type="text" label="Username" value=componentUsername onChange=onUsernameChanged />
      );
    ;

所以,我将value 绑定到组件中的自定义变量,当输入字段的内容发生更改时,该变量也会更改。

为什么输入框组件没有用新的用户名更新自己?

亲切的问候,

【问题讨论】:

你能搞定一个小提琴并运行吗? 无状态组件是无状态的。它们应该被实现为纯函数。返回值应仅取决于参数(道具)。由于没有任何东西改变道具 - 不会发生重新渲染。但是您的组件实际上并不是无状态的,它们确实具有可变的内部状态(输入值)。因此,您需要同时实现这两者或容器一个作为有状态组件。 【参考方案1】:

功能组件的想法是不对状态或道具进行任何更改。

由于没有重新渲染组件的触发器,因此您不会看到任何变化。

将此React.Function 更改为React.Component

const InputField = (props) =>   
  const InputFieldContentsChanged = (event) => 
    console.log(event.target.value);
    props.onChange(event.target.value);
  ;

  return (
    <div data-component="input-field"
      className=(props.value !== "" ? "value": "")>
      <input type=props.type value=props.value onChange=InputFieldContentsChanged />
      <span className="bar"></span>
      <label>props.label</label>
    </div>
  );
;

class SampleComponent extends React.Component 
  constructor() 
    super();
    this.state =  componentUsername : "";
  
  
  onUsernameChanged = (username) => 
    console.log(username);
    this.setState(componentUsername: username);
  
  
  render() 
    return (
      <InputField type="text" label="Username" value=this.state.componentUsername onChange=this.onUsernameChanged />
    );
  
;

ReactDOM.render(<SampleComponent/>, document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>

【讨论】:

【参考方案2】:

我正在编写一个无状态的 React 组件,因为最好的做法是在不需要时避免状态。

在您的代码中,您尝试使用自己的“状态”,它只是一个变量 (componentUsername)。但由于它不是 React 状态,因此组件不会在变量更改时重新渲染。 React 根本不知道变化。

因此,要么使用通常的setState 而不是重新分配您自己的“状态”变量,或者将逻辑放在父组件中并通过道具将componentUsername 传递给SampleComponent

const SampleComponent = props => (
  <input type="text" onChange=props.onChange value=props.value />
);

class ParentComponent extends React.Component 
  constructor() 
    super();
    this.state =  value: '' ;
    this.handleInputChange = this.handleInputChange.bind(this);
  

  handleInputChange(e) 
    console.log(e.target.value);
    this.setState( value: e.target.value );
  

  render() 
    return (
      <SampleComponent
        value=this.state.value
        onChange=this.handleInputChange
      />
    );
  


ReactDOM.render(<ParentComponent />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>

【讨论】:

谢谢。如果我没听错的话,“top-root”组件应该有“state”才能触发重新渲染,对吗? 另一件事,如果我将 componentUsername 作为属性分配给 InputField,那么由于组件无法更新它自己的 props,我该如何触发重新渲染? 是的,没错!当然,像 Redux 或 Mobx 这样的状态容器也有例外。 因为父组件更新了SampleComponent的props。 componentUsername 在这种情况下应该是父状态的一部分。 好的,这就很清楚了。你能给我以下建议吗?我应该在父组件中维护状态,还是应该在 InputField 组件本身中使用内部状态?

以上是关于更改值后反应组件未更新的主要内容,如果未能解决你的问题,请参考以下文章

无法对未安装的组件执行 React 状态更新(useEffect 反应挂钩)

反应功能组件未从父组件更新 setState

商店状态更改时反应组件不更新

反应无状态子组件不会更新父组件中的状态更改

如何调试反应路由器未在 url 更改时加载组件

反应钩子。无法对未安装的组件执行 React 状态更新