【问题标题】:Can we pass setState as props from one component to other and change parent state from child component in React?我们可以将 setState 作为 props 从一个组件传递到另一个组件并在 React 中从子组件更改父状态吗?
【发布时间】:2018-05-07 13:25:04
【问题描述】:
 class App extends Component {
  constructor() {
    super();
    this.state = {
      name: 'React'
    };
    this.setState=this.setState.bind(this)
  }

  render() {
    return (
      <div>
        <Hello name={this.state.name} />
        <p>
          Start editing to see some magic happen :)
        </p>
        <Child {...this}/>
      </div>
    );
  }
}

child Component
var Child=(self)=>{
  return(
    <button  onClick={()=>{
      self .setState({
        name:"viswa"
      })
    }}>Click </button>
  )

这里我绑定了 setState 函数并将其作为 props 发送给子组件。这将改变父组件的状态。这是正确的方法吗?

【问题讨论】:

  • 最好传递一个父函数来改变状态。
  • 但这比传递函数简单。如果我想改变很多状态变化。与传递函数相比,这将是一种简单快捷的方式吗?@yBrodsky
  • 我对反应只有理论经验。但我从来没有见过这个。他们一直在传递函数。
  • @yBrodskyYeah。我只是试试这个。它也在工作。我想不会有任何错误。如果我还是喜欢这个,谢谢
  • 我强烈反对这种方法。虽然它会起作用,但这样做是非常反模式的。无论如何,您可能需要this 的唯一东西是state。因此,与其传递整个实例,不如传递一个让您完全控制状态的函数。

标签: javascript reactjs function setstate react-props


【解决方案1】:

但这比传递函数简单。如果我想更改许多状态更改。与传递函数相比,这将是一种简单快捷的方式吗?

执行此操作的正确方法与您的一样简单,并且不违反最佳实践:

class App extends Component {
  state = {
      name: 'React',
  };

  render() {
    return (
      <div>
        <Hello name={this.state.name} />
        <p>
          Start editing to see some magic happen :)
        </p>
        <Child onClick={() => this.setState({name: 'viswa'})}/>
      </div>
    );
  }
}

const Child=({onClick})=>(
    <button onClick={onClick}>Click</button>
);

【讨论】:

  • 你将函数作为道具发送给孩子。我也将 setState 函数作为道具发送。所以两者都一样吧?
  • @viswaram 通过将setState 传递给孩子,您将暴露父母的内部。您的孩子必须知道状态是如何实现的,因此您不能重用子组件。这不是一个好的做法,对正确的做法没有任何好处。
【解决方案2】:

您不应该直接传递 setState,因为 setState 函数不会立即更改状态。

正如documents所说:

将 setState() 视为请求而不是立即命令 更新组件。为了获得更好的感知性能,React 可能 延迟它,然后一次更新几个组件。反应 不保证立即应用状态更改。

setState() 并不总是立即更新组件。它可能会批量更新或将更新推迟到以后。因此,您最好一起管理 setState 函数的调用,因为可能存在变异父状态的竞争。不建议将此函数传递给其他组件。

将setState函数的调用封装在一个类中,让代码更强大。

【讨论】:

    【解决方案3】:

    我猜在功能组件中可以将你的 setState 发送给子组件并更改它们的父状态,但不能在类基组件中

    【讨论】:

    • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
    【解决方案4】:

    正如@yBrodsky 所说,您应该传递一个确实会改变状态的函数。这是一个例子:

    class App extends Component {
      constructor() {
        super();
        this.state = {
          name: 'React'
        };
        this.update=this.update.bind(this);
      }
    
      update(nextState) {
        this.setState(nextState);
      }
    
      render() {
        return (
          <Child updateParent={this.update} />
        );
      }
    }
    
    const Child = ({updateParent}) => (
      <button onClick={() => updateParent({name: 'Foo bar'})}>Click</button>
    );
    

    您现在可以完全控制子项中父项的状态。只需将要浅合并到父状态的对象传递。在此示例中,App 中的 name 在按钮单击时将更改为 Foo bar

    【讨论】:

    • 谢谢。我可以这样做。但是如果我将其作为道具发送。我可以完全控制所有状态,父组件的所有道具。我可以访问任何状态和任何道具.这类似于传递道具。我不明白为什么这不是正确的方式?
    • 在很多方面都是错误的。重要的是要记住this 不仅仅是stateprops 以及您可能拥有的任何组件功能。这是整个实例。它不仅没有必要,而且还会干扰 Child 组件的重新渲染方式。如果将父级的this 变成子级的道具,任何内部“幕后”更改都可能导致组件重新渲染。它可能有效,并且在您看来可能很灵活,但是如果您想实现“正确的编程实践”,则应不惜一切代价避免使用您的方法。
    • 谢谢你。@Chris.我以后会避免这种情况
    • 这确实有效,但它将子组件与父实现耦合在一起,可以被认为是一种不好的做法。为父级感兴趣的所有事件显式定义回调接口几乎总是更好。
    • @trixn,OP 表示如果他们需要多次状态更改,他们需要一个灵活的解决方案。我同意最好为每个状态更改定义专用函数,但我也不同意这是不好的做法(如果前一种方法不可行)。这里唯一的区别是您传递的是键值(通过对象),而不仅仅是来自 Child 的值,然后与 Parent 中的键耦合。这两种方法仍然会生成键值对以浅层合并到状态中。
    猜你喜欢
    • 2021-01-11
    • 2019-09-26
    • 1970-01-01
    • 1970-01-01
    • 2020-03-12
    • 2021-01-02
    • 2020-06-05
    • 2018-09-28
    • 2019-12-11
    相关资源
    最近更新 更多