反应,如何从父母访问孩子的状态?无需更新父级状态 [英] React, how to access child's state from parent? no need to update parent's state

查看:65
本文介绍了反应,如何从父母访问孩子的状态?无需更新父级状态的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对React很新,并且非常难以绕过整个州管理层,并通过状态和道具传递数据。我确实理解标准的反应方式是以单向方式传递数据 - 从父节点到子节点,我已经为所有其他组件这样做了。
但我有一个名为Book的组件,它根据用户选择表单'read,wantToRead,currentReading和none'改变其shelf状态。在我的BookList组件中呈现Book组件,但它需要能够读取Book的架子状态并在名为read,wantToRead,currentReading和none的部分下呈现正确的书籍。而且由于在这种情况下,Book组件是从BookList组件呈现的,而BookList是父组件,我真的无法理解如何启用BookList来访问Book的状态?
BookList组件:

Hi I am pretty new to React and having really hard time wrapping my head around this whole state management and passing data through state and props. I do understand that the standard react way is to pass down data in a unidirectional way- from parent to child, which I have done so for all other components. But I have this component called Book, which changes its 'shelf' state, based on user selection form 'read, wantToRead, currentlyReading, and none'. And in my BookList component which renders Book component, but it needs to be able to read Book's shelf state and render the correct books under sections called 'read, wantToRead, currentlyReading, and none'. And since in this case, Book component is being rendered from BookList component and BookList being the parent, i really cannot understand how to enable BookList to access Book's state? BookList component:

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中我有:

in my app.js i have:

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

现在,当我在浏览器中打开书单组件时,我没有书籍,因为它没有在任何if语句中获取状态:

Right now, when i open the booklist component in browser, i get no books because it's not picking up the state in any of the if statements here:

if (shelf === 'currentlyReading'){
                return <div className="bookshelf-books">
}

非常感谢您提前阅读,任何帮助都会很多不胜感激!
谢谢!

Thank you so much in advance for reading through and, any help would be much appreciated! Thank you!

推荐答案

你不需要访问孩子的状态,你可以通过回调从父级到子级的处理程序,当在子级内部触发事件时,您可以通过该事件处理程序(回调)通知父级。

我将发布一个小例子:

You don't need to "access" the child's state, you can pass a callback handler from the parent to the child and when an event is triggered inside the child you can notify the parent through that event handler (callback).
I'll post a small example:

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>

这篇关于反应,如何从父母访问孩子的状态?无需更新父级状态的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆