ReactJS:子组件内父级的setState

时间:2015-03-17 13:48:36

标签: reactjs

在子组件的父级上执行setState的建议模式是什么。

var Todos = React.createClass({
  getInitialState: function() {
    return {
      todos: [
        "I am done",
        "I am not done"
      ]
    }
  },

  render: function() {
    var todos = this.state.todos.map(function(todo) {
      return <div>{todo}</div>;
    });

    return <div>
      <h3>Todo(s)</h3>
      {todos}
      <TodoForm />
    </div>;
  }
});

var TodoForm = React.createClass({
  getInitialState: function() {
    return {
      todoInput: ""
    }
  },

  handleOnChange: function(e) {
    e.preventDefault();
    this.setState({todoInput: e.target.value});
  },

  handleClick: function(e) {
    e.preventDefault();
    //add the new todo item
  },

  render: function() {
    return <div>
      <br />
      <input type="text" value={this.state.todoInput} onChange={this.handleOnChange} />
      <button onClick={this.handleClick}>Add Todo</button>
    </div>;
  }
});

React.render(<Todos />, document.body)

我有一系列todo项目,这些项目都保持在父母的状态。 我想访问父级的状态,并从TodoForm的{​​{1}}组件中添加新的待办事项。 我的想法是在父级上执行一个setState,它将呈现新添加的待办事项。

7 个答案:

答案 0 :(得分:59)

在您的父级中,您可以创建一个类似addTodoItem的函数,它将执行所需的setState,然后将该函数作为props传递给子组件。

var Todos = React.createClass({

  ...

  addTodoItem: function(todoItem) {
    this.state.todos.push(todoItem);
    this.setState({todos: this.state.todos});
  },

  render: function() {

    ...

    return <div>
      <h3>Todo(s)</h3>
      {todos}
      <TodoForm addTodoItem={this.addTodoItem} />
    </div>
  }
});

var TodoForm = React.createClass({
  handleClick: function(e) {
    e.preventDefault();
    this.props.addTodoItem(this.state.todoInput);
    this.setState({todoInput: ""});
  },

  ...

});

您可以在TodoForm的handleClick中调用addTodoItem。这将在父级上执行setState,它将呈现新添加的待办事项。希望你明白这一点。

Fiddle here.

答案 1 :(得分:5)

您可以在父组件中创建addTodo函数,将其绑定到该上下文,将其传递给子组件并从那里调用它。

// in Todos
addTodo: function(newTodo) {
    // add todo
}

然后,在Todos.render中,你会做

<TodoForm addToDo={this.addTodo.bind(this)} />

使用

在TodoForm中调用此方法
this.props.addToDo(newTodo);

答案 2 :(得分:5)

这些都是基本正确的,我只是想我会指出新的(ish)官方反应文件基本上建议: -

  

对于在React应用程序中发生变化的任何数据,应该只有一个“真实来源”。通常,首先将状态添加到需要渲染的组件中。然后,如果其他组件也需要它,您可以将它提升到最近的共同祖先。您应该依赖自上而下的数据流,而不是尝试在不同组件之间同步状态。

https://reactjs.org/docs/lifting-state-up.html。该页面也通过一个例子。

答案 3 :(得分:2)

我找到了以下工作和简单的解决方案,将参数从子组件传递到父组件:

//ChildExt component
class ChildExt extends React.Component {
    render() {
        var handleForUpdate =   this.props.handleForUpdate;
        return (<div><button onClick={() => handleForUpdate('someNewVar')}>Push me</button></div>
        )
    }
}

//Parent component
class ParentExt extends React.Component {   
    constructor(props) {
        super(props);
        var handleForUpdate = this.handleForUpdate.bind(this);
    }
    handleForUpdate(someArg){
            alert('We pass argument from Child to Parent: \n' + someArg);   
    }

    render() {
        var handleForUpdate =   this.handleForUpdate;    
        return (<div>
                    <ChildExt handleForUpdate = {handleForUpdate.bind(this)} /></div>)
    }
}

if(document.querySelector("#demo")){
    ReactDOM.render(
        <ParentExt />,
        document.querySelector("#demo")
    );
}

Look at JSFIDDLE

答案 4 :(得分:0)

对于那些使用React Hook useState保持状态的人,我根据以上建议修改了下面的演示滑块应用程序。在演示应用中,子滑块组件会保持父状态。

该演示还使用了useEffect钩子。 (而且更不重要的是,useRef钩子)

import React, { useState, useEffect, useRef } from "react";

//the parent react component
function Parent() {

  // the parentState will be set by its child slider component
  const [parentState, setParentState] = useState(0);

  // make wrapper function to give child
  const wrapperSetParentState = val => {
    setParentState(val);
  };

  return (
    <div style={{ margin: 30 }}>
      <Child
        parentState={parentState}
        parentStateSetter={wrapperSetParentState}
      />
      <div>Parent State: {parentState}</div>
    </div>
  );
};

//the child react component
function Child(props) {
  const childRef = useRef();
  const [childState, setChildState] = useState(0);

  useEffect(() => {
    props.parentStateSetter(childState);
  }, [childState]);

  const onSliderChangeHandler = e => {
  //pass slider's event value to child's state
    setChildState(e.target.value);
  };

  return (
    <div>
      <input
        type="range"
        min="1"
        max="255"
        value={childState}
        ref={childRef}
        onChange={onSliderChangeHandler}
      ></input>
    </div>
  );
};

export default Parent;

答案 5 :(得分:0)

如果您将类组件作为父组件使用,则将setState传递给子代的一种非常简单的方法是在arrow函数中传递它。这在设置可以传递的提升环境时起作用:

class ClassComponent ... {

    modifyState = () =>{
        this.setState({...})   
    }
    render(){
          return <><ChildComponent parentStateModifier={modifyState} /></>
    }
}

答案 6 :(得分:-1)

parentSetState={(obj) => { this.setState(obj) }}