В этом посте я объясню, как передавать состояние между компонентами в Reactjs. Мы создадим небольшое приложение Сколько книг вы прочитали?, в этом приложении у нас есть два основных компонента: один большой под названием Библиотека и другой маленький Книга, у нас есть 3 книги в состоянии библиотеки, и каждая книга имеет свое государство. проверьте любую книгу, чтобы считать ее прочитанной. попробовать приложение здесь
Начнем с кода:
Передача состояния от родителя к дочернему
В нашем компоненте библиотеки у нас есть это состояние
this.state = {
reads: 0,
books: [
{
name: 'Zero to one',
isbn: '9780804139298',
author: 'Peter Thiel',
cover: 'https://images.gr-assets.com/books/1414347376l/18050143.jpg',
status: false
},
{
name: "The Manager's Path",
isbn: '9781491973899',
author: 'Camille Fournier',
cover: 'https://images.gr-assets.com/books/1484107737l/33369254.jpg',
status: false
},
{
name: 'Calculus, Better Explained',
isbn: '9781470070700',
author: 'Kalid Azad',
cover: 'https://images.gr-assets.com/books/1448590460l/27993945.jpg',
status: false
}
]
};
и хотите создать this.state.books.length
— в виде числа — Book
компонентов, каждый из которых имеет свойства из массива books
состояния Library
компонента. Мы должны иметь дело с двумя компонентами.
Сначала с родителем мы должны создать компонент Book
this.state.books.length
- в виде числа - раз и передать им наши разные значения. Вот так:
{
this.state.books.map((_book, _id) => {
return (
<Book
handleCounter={this.handleCounter}
key={_id}
id={_book.isbn}
name={_book.name}
isbn={_book.isbn}
author={_book.author}
cover={_book.cover}
/>
);
});
}
Примечание пока игнорируйте handleCounter
.
Во-вторых с дочерним элементом Book
, у нас есть значения от родителя, давайте использовать их:
...
render() {
return (
<Card>
<Image
src={this.props.cover}
alt="Book cover"
...
До сих пор мы создали 3 компонента Book
из родительского компонента Library
и устанавливали их значения из родительского состояния. Легкий! Правильно? Отлично, начинаем вторую часть
Передача состояния от дочернего к родительскому
В этом разделе мы хотим обрабатывать количество прочитанных вами книг, устанавливая флажок для каждой книги.
В нашем Book
у нас есть это состояние
this.state = {
status: false,
id: this.props.id
};
Примечание не забудьте передать props
конструктору компонента.
status
означает, читали ли вы эту книгу или нет, и его значение по умолчанию — false
, id
— это идентификатор этой книги, и я установил его по идентификатору книги, как мы узнали в предыдущем разделе.
нам нужно обработать изменение этого статуса, а затем обновить массив книг в родительском состоянии.
В нашем компоненте Book
мы добавим флажок, который получает изменение статуса книги и передает this.handleChange
его onChange
событию следующим образом:
<input type="checkbox" name="example" onChange={this.handleChange} />
вам нужно сначала связать функцию, затем обновить состояние Book
с новым статусом, после обновления дочернего состояния мы обновим состояние родителя Library
следующим образом:
handleChange() { this.setState({status: !this.state.status}, this.updateLibraryCount); }
updateLibraryCount() { this.props.handleCounter(this.state); }
В updateLibraryCount
мы использовали handleCounter
функцию Library
в качестве реквизита, затем передали ей состояние Book
. Теперь Library
видит состояние Book
, отлично! давайте использовать его.
handleCounter(_State) { //Get the index of this book by searching by its unique isbn const ObjNum = this.state.books.findIndex( _book => _book.isbn === _State.id );
//then update its value in the Library component this.setState( { books: update( ObjNum, {...this.state.books[ObjNum], status: _State.status}, this.state.books ) }, () => { //this is a callback to handle the new change of the book status and increment the reads const _read = this.state.books.filter(_book => _book.status === true) .length; this.setState({reads: _read}); } ); }
Надеюсь, вы понимаете, как передать состояние от родителя к дочернему и наоборот. Вот полный код, а это оригинальный пост в моем блоге. Если у вас есть вопросы, не стесняйтесь задавать их в комментариях или электронной почте.