React,如何从父母那里访问孩子的状态?无需更新父母的状态
Posted
技术标签:
【中文标题】React,如何从父母那里访问孩子的状态?无需更新父母的状态【英文标题】:React, how to access child's state from parent? no need to update parent's state 【发布时间】:2018-03-19 20:37:21 【问题描述】:您好,我对 React 还是很陌生,我很难完全理解整个状态管理以及通过状态和道具传递数据。我确实明白标准的反应方式是以单向方式传递数据——从父级到子级,我对所有其他组件都这样做了。 但我有一个名为 Book 的组件,它根据用户选择表单“已读、想要读、当前读和无”更改其“搁置”状态。在我的 BookList 组件中,它呈现 Book 组件,但它需要能够读取 Book 的书架状态并在名为“read、wantToRead、currentReading 和 none”的部分下呈现正确的书籍。由于在这种情况下,Book 组件是从 BookList 组件呈现的,而 BookList 是父组件,我真的无法理解如何使 BookList 能够访问 Book 的状态? BookList 组件:
import React, Component from 'react'
import Link from 'react-router-dom'
import Book from './Book'
class BookList extends Component
render()
const books, shelf = this.props
return (
<div className="list-books">
<div className="list-books-content">
<div className="list-books-title">
<h1>MyReads</h1>
</div>
<div className="bookshelf">
<h2 className="bookshelf-title">None</h2>
books.map((book)=>
console.log(book)
if (shelf === '')
return <div className="bookshelf-books">
/* <BookStateless book= book /> */
<Book book = book />
/* <BookStateless book= book /> */
</div>
)
</div>
<div className="bookshelf">
<h2 className="bookshelf-title">Currently Reading</h2>
books.map((book)=>
if (shelf === 'currentlyReading')
return <div className="bookshelf-books">
/* <BookStateless book= book /> */
<Book book = book />
</div>
// console.log(this.book.title, this.book.state)
)
</div>
<div className="bookshelf">
<h2 className="bookshelf-title">Want to Read</h2>
books.map((book)=>
if (shelf === 'wantToRead')
return <div className="bookshelf-books">
/* <BookStateless book= book /> */
<Book book = book />
/* <BookStateless book= book /> */
</div>
// console.log(this.book.title, this.book.state)
)
</div>
<div className="bookshelf">
<h2 className="bookshelf-title">Read</h2>
books.map((book)=>
if (shelf === 'read')
console.log(shelf)
return <div className="bookshelf-books">
/* <BookStateless book= book /> */
<Book book = book />
</div>
// console.log(this.book.title, this.book.state)
)
</div>
</div>
<div className="open-search">
<Link to="/search">Add a book</Link>
</div>
</div>
)
export default BookList
图书组件:
import React, Component from 'react'
// import * as BooksAPI from './BooksAPI'
import Select from 'react-select'
import 'react-select/dist/react-select.css'
class Book extends Component
state=
// state can be read, none, want to read, or currently reading
shelf: ''
handleChange(e)
this.setState( shelf: e['value'] )
console.log("this?", this)
render()
const book = this.props
const shelf = this.state
console.log("book", book.state)
const options = [
value: 'currentlyReading', label: 'currentlyReading',
value: 'wantToRead', label: 'wantToRead',
value: 'read', label: 'read',
value: 'none', label: 'none'
]
return (
<li key=book.id>
<div className="book">
<div className="book-top">
<div className="book-cover" style= width: 128, height: 188, backgroundImage: `url("$book.imageLinks.thumbnail")` ></div>
<div className="book-shelf-changer">
<Select
value=""
options=options
onChange=(e)=>this.handleChange(e)
/>
</div>
</div>
<div className="book-title">book.title</div>
<div className="book-authors">book.authors</div>
</div>
</li>
)
export default Book
在我的 app.js 中我有:
import React from 'react'
import * as BooksAPI from './BooksAPI'
import './App.css'
import Search from './Search'
import BookList from './BookList'
import Book from './Book'
import Route from 'react-router-dom'
class BooksApp extends React.Component
state =
books : []
componentDidMount()
BooksAPI.getAll().then((books)=>
this.setState( books: books )
// console.log("bookstest",this)
)
render()
return (
<div className="App">
<Route exact path="/" render=()=>(
<Book books=this.state.books />
) />
<Route path="/search" render=()=>(
<Search books=this.state.books />
) />
<Route path="/BookList" render=()=>(
<BookList books=this.state.books />
) />
</div>
)
export default BooksApp
现在,当我在浏览器中打开 booklist 组件时,我没有得到任何书籍,因为它没有在此处的任何 if 语句中获取状态:
if (shelf === 'currentlyReading')
return <div className="bookshelf-books">
非常感谢您提前阅读,任何帮助将不胜感激! 谢谢!
【问题讨论】:
你在哪里为书单建立路由 url? 这能回答你的问题吗? How to access child's state in React? 【参考方案1】:您不需要“访问”子级的状态,您可以将回调处理程序从父级传递给子级,当子级内部触发事件时,您可以通过该事件处理程序(回调)通知父级。 我将发布一个小例子:
class Book extends React.Component
handleClick = e =>
const bookId, onToggleBook = this.props;
onToggleBook(bookId);
;
render()
const name, isRead = this.props;
return (
<div className=`$isRead && "read"` onClick=this.handleClick>
<span>name</span>
isRead && <i> - You read me</i>
</div>
);
class App extends React.Component
constructor(props)
super(props);
this.state =
books: [
id: 1,
name: "book 1",
isRead: false
,
id: 2,
name: "book 2",
isRead: false
,
id: 3,
name: "book 3",
isRead: true
,
id: 4,
name: "book 4",
isRead: false
]
;
onToggleBookStatus = bookid =>
const books = this.state;
const nextBookState = books.map(book =>
if (book.id !== bookid) return book;
return
...book,
isRead: !book.isRead
;
);
this.setState(prevState => ( books: nextBookState ));
;
render()
const books = this.state;
return (
<div>
<div>My Books</div>
books.map(book => (
<Book
key=book.id
isRead=book.isRead
name=book.name
bookId=book.id
onToggleBook=this.onToggleBookStatus
/>
))
</div>
);
ReactDOM.render(<App />, document.getElementById("root"));
.read
color: red;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
【讨论】:
老兄,你刚刚给了我开启我心中 React 智慧的钥匙!非常感谢!!【参考方案2】:如您所知,要将某些东西从父级传递给子级,您需要使用道具。为了从孩子那里得到一些东西给父母,你再次使用道具,但这次你将一个函数传递给孩子,然后孩子调用那个函数。
例如,您可以将孩子的句柄更改功能修改为如下所示:
handleChange(e)
if (this.props.onShelfChanged)
this.props.onShelfChanged(e.value);
this.setState( shelf: e.value )
然后在父级中,您需要将 onShelfChanged 属性传递给 book,以便在值更改时收到通知。像这样的:
// in the render function
books.map((book, index) =>
<Book book=book onShelfChanged=() => this.childBookChanged(index)
);
您需要创建并填写 childBookChanged 函数来执行您需要执行的任何更新。
需要注意的一点是,您不希望手动保持书籍和书架同步。 Book
正在跟踪它自己的某些状态,然后您将其传递出去并可能改变书架的状态。随着应用程序的增长,保持这些同步可能是一件令人头疼的事情,也是错误的来源。相反,您应该有一段代码负责,它看起来很可能是书架(因为它是关心此状态的最顶层组件)。因此,您很可能希望从 Book
中删除内部状态,而是通过 props 告诉本书该做什么。
如果您需要 Book
组件有时作为独立组件工作,有时在书架内工作,那么您可能需要做更多工作以使其同时支持“受控”和“不受控”实现,但是对于受控情况,将状态向上移动仍然是一个好主意。您可以阅读更多关于受控和非受控组件here 和here
【讨论】:
以上是关于React,如何从父母那里访问孩子的状态?无需更新父母的状态的主要内容,如果未能解决你的问题,请参考以下文章
问题:为什么在我为孩子设置状态时,React为什么更新我的父母?仅发生在数组
当孩子必须更新父母的状态时,this.setState 不起作用