在子组件的父级上执行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,它将呈现新添加的待办事项。
答案 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,它将呈现新添加的待办事项。希望你明白这一点。
答案 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")
);
}
答案 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) }}