【问题标题】:How to update parent's state?如何更新父母的状态?
【发布时间】:2017-11-23 11:58:28
【问题描述】:

我刚开始做出反应并尝试更新父母的状态,但到目前为止还没有运气。

组件

class InputBox extends Component {
  constructor(props) {
    super(props);
    this.type = props.type;
  }
  render() {
    return (
      <div>
        <input type={this.type}/>
      </div>
    );
  }
}

我想使用此组件切换密码的其他容器

constructor(props) {
  super(props);
  this.state = {
    type: 'password',
    wording: 'Show',
  };
  this.changeState = this.changeState.bind(this);
}

changeState() {
  const oldState = this.state.type;
  const isTextOrHide = (oldState === 'password');
  const newState = (isTextOrHide) ? 'text' : 'password';
  const newWord = (isTextOrHide) ? 'Hide' : 'Show';
  this.setState({
    type: newState,
    label: newWord,
  });
}

<Wrapper>
  <InputBox type={this.state.type} />
  <Toggle onClick={this.changeState}>{this.state.wording}</Toggle>
</Wrapper>

【问题讨论】:

标签: javascript reactjs jsx


【解决方案1】:

你可以这样做:

首先,父组件:

import React, { Component } from 'react';
import { InputBox} from './InputBox'

class componentName extends Component {
  state = {
    password: '',
    type: 'password',
    wording: 'Show',
  }

  handleShow = (word) => {
    this.setState({ wording: word })
  }

  handleChange = (e) => {
    if(!this.state.password){ 
      handleShow('Show')
    } else  {
      handleShow('Hide')
    }
    this.setState({ password: e.target.value })
  }

  render() {
    return (
      <div>
        <Wrapper>
          <InputBox
           name='password'  
           handleChange={this.handleChange} 
           password={this.state.password}
           type={this.state.type} /> . 
          <Toggle onClick={this.changeState}>{this.state.wording}
         </Toggle>
        </Wrapper>
      </div>
    );
  }
}

现在是子组件:

import React from 'react';

export const InputBox = (props) => (
  <input onChange={props.handleChange} value={props.password} type={props.type}/>
)
  1. state 需要始终保留在父级中,然后通过props 向下传递
  2. 子组件通常是无状态的,这意味着,它们不需要是class(可以只是一个返回jsx的函数)和最重要的,不能有state(状态仅适用于Class components)

始终将状态传递给子组件 因为无论state 向下多远,通过props 它总是会改变源,在这种情况下是父级,即状态的创建者

另一个重要的事情:

如果您使用箭头函数 ES6 ,则无需 constructor 来绑定您的函数。

像这样:handleSomething = () =&gt; { return ... }

另一件事:

你不需要constructor来设置state,你可以简单地做

state = { } 

它会自动成为上下文的一部分this

这样想你永远不会失败。

希望对你有帮助:)

【讨论】:

    【解决方案2】:
    class Child extends Component{
        constructor(props){
           super(props);
        }
    
        render(){
           let { parentStateChange } = this.props;
           return <input type='text' onChange={parentStateChange}/>
        }
    }
    
    class Parent extends Component{
        constructor(props){
           super(props);
           this.state = {
               content: "Something"
           }
           this.parentStateChange = this.parentStateChange.bind(this);
        }
    
        parentStateChange(event){
           let value = event.target.value;
           this.setState({
               content: value
           })
        }
    
        render(){
           let { content } = this.state;
           return <div>
               <h2>{content}</h2>
               <Child parentStateChange={this.parentStateChange}></Child>
             </div>
        }
    }
    

    我通过将 Parent 的方法作为道具传递给孩子来做到这一点。然后 Child 使用此方法更改 Parent 的状态。它被称为回调函数。

    For More References

    我认为这对你很有用。

    【讨论】:

      【解决方案3】:

      更通用(但可能是不好的方法)。父类有一个函数作为回调传递给子类,并允许子类直接调用 setState。我只能在有几个孩子的紧密绑定的小组件中看到这很有用,或者仅用于概念验证代码。

      /**
        * This allows children to set state of this object.
        * Might be a very bad approach, btw.
        * 
        * @param {object} newState - object to update state.
        * @param {func} cb - call back after state is updated.
        */
       doSetState = (newState, cb=null) => {
          const merge = { ...this.state, ...newState };
          cb ? this.setState(merge, cb) : this.setState(merge);
      }
      

      【讨论】:

        猜你喜欢
        • 2020-03-07
        • 2018-03-19
        • 1970-01-01
        • 2021-01-21
        • 1970-01-01
        • 2017-12-28
        • 1970-01-01
        • 1970-01-01
        • 2021-03-08
        相关资源
        最近更新 更多