更新父组件的状态以响应子组件状态变化:ReactJS

huangapple go评论75阅读模式
英文:

ReactJS: Updating Parent component's states from Child components state change

问题

我目前正在创建一个ReactJS项目,其中我想创建一个可重复使用的组件,包括复选框和文本输入字段(即待办事项列表项)。我的React解决方案的当前结构如下:

<Parent>

--| <Child value={text1} checked={false} />
--| <Child value={text2} checked={false} />

</Parent>

在这个结构中,传递给子组件的valuechecked将用于复选框和文本字段输入:

基本上我现在遇到的主要问题是,当我尝试在子组件中更改状态,并且该状态是从父组件传递的属性值引用时,React会出现未捕获的错误,网页因无限渲染而冻结(我假设是这个原因)。我不知道如何以正确的方式更新父组件的状态,基于子组件的引用以及其中的更改。

是否有可能使用React中的hooks或createRef之类的方式引用子组件对父组件的更改,还是我应该将react-redux应用于我的项目以解决这种问题?

编辑:我根据一个答案的建议进行了一些更改,该答案指出了处理stateprops的问题。我在父组件中创建了一个handleInputChange函数,根据传递给子组件中指定的键值来更新状态。然而,仍然存在以下问题:

  • 渲染循环仍然发生。
  • event.target.value 为 undefined。

父子组件如下所示(用于输入文本更新):

export class Parent extends Component {
   constructor(props) {
     super(props);
     this.state = {
        text1: '',
        text2: '',
        isCheckedAll: false
     }
     this.handleInputChange = this.handleInputChange.bind(this);
   }
   handleInputChange = (key) => {
     switch (key) {
       console.log("在组件上更新:", key);
       case 'key1':
          this.setState({ text1: Event.target.value });
          break;
       case 'key2':
          this.setState({ text2: Event.target.value });
          break;
       default:
          break;
     }
   }

   render() {
     return (
        <Child value={this.state.text1} onChange={() => this.handleInputChange('key1')} checked={false} />
        <Child value={this.state.text2} onChange={() => this.handleInputChange('key2')} checked={false} />
     )
   }
}
export class Child extends Component {
  constructor(props) {
    super(props);
  }

  render() {
    return (
       <>
         <div className="checkbox-wrapper">
            <label>
                <input type="checkbox" checked={this.props.checked} />
            </label>
         </div> 

         <div className="input text-bar">        
           <label>
             <p className="input-label">Input field: </p>
             <input name={this.props.value} className="text-box" type="text" onChange={this.props.onChange} />
           </label>
         </div>
       </>
    )
  }
}

请注意,我已经更正了onChange属性的大小写错误,并将其从子组件传递给父组件的handleInputChange函数中。此外,我还更正了在handleInputChange函数中使用的Event,应该是event

英文:

I am currently creating a ReactJS project where I want to make a recyclable component consist of a checkbox and a textfield input (i.e a Todo list item). The current structure of my React solution is something like this:

&lt;Parent &gt;

--| &lt;Child value={text1} checked= false/&gt;
--| &lt;Child value={text2} checked= false/&gt;


&lt;/Parent&gt;

In which the value and checked passed down to the child component will be used for the checkbox and text field input:

Basically the main problem I have now is that when I try to change the state inside the child component, and that state is referenced from property values passed down from the parent component, React will have uncaught error and the web page froze up due to unlimited rendering (in my assumption). And I don't know what is the proper solution where I can update the parent's state based on how it got referenced to the child component and change inside that.

Is there any possible way to reference the change from the child component to the parent component with react like using hooks or creatRef, or should I apply react-redux into my project for this type of problem?

Edited: I have made some changes based on the suggestion from one of the answers that state the issue of handling state and props. In which I create a handleInputChange function in the parent component to update the state based on passing key value which is specified in the child components. However there are still issues:

  • The rendering loop still happens.
  • The event.target.value is undefined

The parent-child component like following (for input text update):

export class Parent extends Component {
   constructor(props) {
     super(props);
     this.state = {
        text1 = &#39;&#39;;
        text2 = &#39;&#39;;
        isCheckedAll = false;
     }
     this.handleInputChange = this.handleInputChange.bind(this);
   }
   handleInputChange = (key) =&gt; {
     switch (key) {
       console.log(&quot;Updating on component: &quot;, key);
       case &#39;key1&#39;:
          this.setState({text1 : Event.target.value});
          break;
       case &#39;key2&#39;:
          this.setState({text2 : Event.target.value});
          break;
       default:
          break;
     }
   }

   render() {
     return (
        &lt;Child value={this.state.text1}, onchange= this.handleInputChange(&#39;key1&#39;) checked = false&gt;
        &lt;Child value={this.state.text1}, onchange= this.handleInputChange(&#39;key1&#39;) checked = false&gt;
     )
   }
}
export class Child extends component {
  constructor(props) {
    super(props);
  }


  render() {
    return (
       &lt;&gt;
         &lt;div className=&quot;checkbox-wrapper&quot;&gt;
            &lt;label&gt;
                &lt;input type=&quot;checkbox&quot; checked={this.props.checked} /&gt;
            &lt;/label&gt;
         &lt;/div&gt; 

         &lt;div className=&quot;input text-bar&quot;&gt;        
           &lt;label&gt;
             &lt;p className=&quot;input-label&quot;&gt;Input field: &lt;/p&gt;
             &lt;input name={this.props.value} className=&quot;text-box&quot; type=&quot;text&quot; onChange={this.props.onChange} /&gt;
           &lt;/label&gt;
         &lt;/div&gt;
       &lt;/&gt;
    )
  }
}

答案1

得分: 1

问题很明确:

> 在其中,传递给子组件的值和检查值将用于复选框和文本字段输入

这意味着checkedvalue不应该是子组件的状态。父组件拥有这些属性,而不是子组件。父组件应该向子组件传递回调函数,以便子组件可以告诉父组件用户执行了某些操作,应该在父组件的状态中更新这些属性

这是我在官方React文档中找到的最相关的内容:

https://legacy.reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html#anti-pattern-unconditionally-copying-props-to-state

英文:

The problem here is clear:

> In which the value and checked passed down to the child component will be used for the checkbox and text field input

This means that checked and value should not be state in the child component. The parent component owns these properties, not the child. The parent should pass a callback to the child so the child can let the parent know that the user did something and the properties should be updated in the parent's state

This is the closest I could find in the official react docs:

https://legacy.reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html#anti-pattern-unconditionally-copying-props-to-state

huangapple
  • 本文由 发表于 2023年6月29日 08:01:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/76577361.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定