Apa pola yang direkomendasikan untuk melakukan setState pada induk dari komponen anak.
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)
Saya memiliki larik item rencana yang dipertahankan dalam status induk. Saya ingin mengakses status induk dan menambahkan item rencana baru, dari komponen TodoForm
's handleClick
. Ide saya adalah melakukan setState pada induknya, yang akan membuat item rencana yang baru ditambahkan.
setState(...): Can only update a mounted or mounting component. This usually means you called setState() on an unmounted component. This is a no-op. Please check the code for the MyModal component.
Jawaban:
Di orang tua Anda, Anda dapat membuat fungsi seperti
addTodoItem
yang akan melakukan setState yang diperlukan dan kemudian meneruskan fungsi itu sebagai props ke komponen anak.var Todos = React.createClass({ ... addTodoItem: function(todoItem) { this.setState(({ todos }) => ({ todos: { ...todos, todoItem } })); }, 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: ""}); }, ... });
Anda dapat memanggil
addTodoItem
di handleClick TodoForm. Ini akan melakukan setState pada induk yang akan membuat item rencana yang baru ditambahkan. Semoga Anda mendapatkan idenya.Biola di sini.
sumber
<<
operator dithis.state.todos << todoItem;
sini?this.state
secara langsung. Lebih baik menggunakan setState fungsional. reactjs.org/docs/react-component.html#setstateIni semua pada dasarnya benar, saya hanya berpikir saya akan menunjuk ke dokumentasi reaksi resmi (ish) baru yang pada dasarnya merekomendasikan: -
Lihat https://reactjs.org/docs/lifting-state-up.html . Halaman ini juga bekerja melalui sebuah contoh.
sumber
Anda bisa membuat fungsi addTodo di komponen induk, mengikatnya ke konteks itu, meneruskannya ke komponen anak dan memanggilnya dari sana.
// in Todos addTodo: function(newTodo) { // add todo }
Kemudian, di Todos.render, Anda akan melakukannya
<TodoForm addToDo={this.addTodo.bind(this)} />
Sebut ini di TodoForm dengan
this.props.addToDo(newTodo);
sumber
bind(this)
pada saat melewatkan fungsi, itu membuang kesalahan fungsi tersebutthis.setState is not a function
.Bagi mereka yang mempertahankan status dengan React Hook
useState
, saya menyesuaikan saran di atas untuk membuat Aplikasi slider demo di bawah ini. Dalam aplikasi demo, komponen penggeser anak mempertahankan status induknya.Demo juga menggunakan
useEffect
hook. (dan yang kurang penting,useRef
kail)import React, { useState, useEffect, useCallback, 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 = useCallback(val => { setParentState(val); }, [setParentState]); return ( <div style={{ margin: 30 }}> <Child parentState={parentState} parentStateSetter={wrapperSetParentState} /> <div>Parent State: {parentState}</div> </div> ); }; //the child react component function Child({parentStateSetter}) { const childRef = useRef(); const [childState, setChildState] = useState(0); useEffect(() => { parentStateSetter(childState); }, [parentStateSetter, 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;
sumber
useEffect
? Mengapa kita perlu menyimpan data di status induk dan anak?parentSetState={(obj) => { this.setState(obj) }}
sumber
Saya menemukan solusi yang berfungsi dan sederhana berikut untuk meneruskan argumen dari komponen anak ke komponen induk:
//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") ); }
Lihat JSFIDDLE
sumber
Jika Anda bekerja dengan komponen kelas sebagai induk, salah satu cara paling sederhana untuk meneruskan setState ke anak adalah dengan meneruskannya di dalam fungsi panah. Ini berfungsi karena menetapkan lingkungan terangkat yang dapat diedarkan:
class ClassComponent ... { modifyState = () =>{ this.setState({...}) } render(){ return <><ChildComponent parentStateModifier={modifyState} /></> } }
sumber