当前位置: 首页 > 知识库问答 >
问题:

如何从Reactjs中的子组件更新父组件状态

申屠锦
2023-03-14

我正在将父组件的状态从父组件传递到子组件。在子组件中,我有一个不同的状态。我正在对子组件的状态执行一些操作,并且结果必须添加到父组件的状态。因此,在我的父组件中,我编写了一个回调函数,该函数将更新父组件的状态。代码为:

updateState = (booksList) => {
          this.setState({books : this.state.books.push(booksList)});
        }

因此,这个函数随后作为道具传递给子组件:

<BookSearch
   books={this.state.books}
   handleShelfChange={this.handleShelfChange}
   updateState={this.updateState}/>

然后在我的子组件中,我试图实现回调函数为:

let getBook = this.state.books.filter(filteredBook => filteredBook.shelf !== "none")
    this.props.updateState(getBook)

但这并没有达到预期效果。这是正确的方法吗?有人能帮我吗?

我试图通过实现这里提供的解决方案来解决我的问题:如何在ReactJS中将数据从子组件传递到其父组件,但是我有一些错误。

编辑

父组件:App.js

import React from 'react'
import * as BooksAPI from './BooksAPI'
import { Link } from 'react-router-dom'
import { Route } from 'react-router-dom'
import './App.css'
import BookList from './BookList'
import BookSearch from './BookSearch'


class BooksApp extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      books: [],
      showSearchPage : false
    };
    //this.updateState = this.updateState.bind(this)
  }

  componentDidMount() {
    BooksAPI.getAll().then((books) => {
      this.setState({ books })
    })
    console.log(this.state.books);
  }

  filterByShelf = (bookName,shelfName) =>
   bookName.filter(book => book.shelf===shelfName)


  isTheBookNew = book => {
    let is = false;
    if (book.shelf === "none")
     { this.setState(state =>
       {
         books: state.books.push(book)});
          is = true;
          console.log(this.state.books);
       }
       return is;
      };

      handleShelfChange = (bookOnChange, newSehlf) => {
         !this.isTheBookNew(bookOnChange) && this.setState(state => {
         let newBooks = state.books.map(book =>
           { if (bookOnChange.id === book.id)
             { book.shelf = newSehlf; }
             return book;
           });
             return {
                books: newBooks
               };
              }
            );
            BooksAPI.update(bookOnChange, newSehlf);
            };

        updateState = (booksList) => {
          const books = [...this.state.books, booksList]
          this.setState({ books });
        }

  render() {
    return (
      <div className="app">
        <Route exact path="/" render={() => (
          <div className="list-books">
              <div className="list-books-title">
                <h1>MyReads</h1>
              </div>

              <BookList
              books={this.filterByShelf(this.state.books,'currentlyReading')}
              shelfName='Currently Reading'
              handleShelfChange={this.handleShelfChange}/>

              <BookList
              books={this.filterByShelf(this.state.books,'wantToRead')}
              shelfName='Want to Read'
              handleShelfChange={this.handleShelfChange}/>

              <BookList
              books={this.filterByShelf(this.state.books,'read')}
              shelfName='Read'
              handleShelfChange={this.handleShelfChange}/>

              <div className="open-search">
                <Link
                to="./search" />
              </div>
          </div>
        )
      } />

            <Route path="/search" render={() =>
                <BookSearch
                 books={this.state.books}
                 handleShelfChange={this.handleShelfChange}
                 updateState={this.updateState}/>
              } />

      </div>
    )
  }
}

export default BooksApp

BookSearch.js:

import React, { Component } from 'react'
import { Link } from 'react-router-dom'
import escapeRegExp from 'escape-string-regexp'
import  sortBy from 'sort-by'
import * as BooksAPI from './BooksAPI'
import BookList from './BookList'

class BookSearch extends Component {
  constructor(props) {
    super(props);
    this.state = {
      search:'',
      books:[]
    }
  }

  updateSearch = (searchString) => {
    this.setState({search: searchString.trim()})
    let searchResults = BooksAPI.search(this.state.search,1).then((book_search) => {
      if (book_search != undefined) {
        console.log(book_search);
          book_search.map((book) => book.shelf = 'none');
          this.setState({ books : book_search }, this.check); // callback function to this.setState
          console.log(this.state.books)
        }
    })

    }


  check = () => {
    let parent_books = this.props.books;
    console.log(this.state.books)
    const book_result = this.state.books.map((book) => {
      const parent = parent_books.find(parent => parent.title === book.title );
       if(parent) {
        //console.log(parent);
        book.shelf = parent.shelf;
        //console.log(book)
          }

        return book;
      })
    this.setState({books: book_result}, () => {console.log(this.state.books)})
  }

  updateParentState = () => {
    let getBook = this.state.books.filter(filteredBook => filteredBook.shelf !== "none")
    this.props.updateState(getBook)

  }

  render() {
    return(

      <div className="search-books">
        <div className="search-books-bar">
          <Link
            to="/"
            className="close-search">
            Close
          </Link>
          <div className="search-books-input-wrapper">
            <input
             type="text"
             placeholder="Search by title or author"
             value={this.state.search}
             onChange={(event) => this.updateSearch(event.target.value)}/>
          </div>
        </div>

        <div className="search-books-results">
          <ol className="books-grid">
            <BookList
              books={this.state.books}
              handleShelfChange={this.props.handleShelfChange}
              updateParentState={this.updateParentState}/>
          </ol>
        </div>
      </div>
    )
  }
}

export default BookSearch

BookList.js

import React, { Component } from 'react';
import Book from './Book'

class BookList extends Component {
constructor(props) {
  super(props);
  this.state = {
    showSearchPage : false
  }
  console.log(this.props.books)
}


  render() {
    return(
      <div className="app">
          <div>
           <div className="list-books-content">
              <div>
                <div className="bookshelf">
                  <h2 className="bookshelf-title">{this.props.shelfName}</h2>
                  <div className="bookshelf-books">
                    <ol className="books-grid">

                      {this.props.books.map(book =>
                        <li key={book.title}>
                          <Book
                          book={book}
                          handleShelfChange={this.props.handleShelfChange}
                          update={this.props.updateParentState} />
                        </li>)
                      }
                    </ol>
                  </div>

                </div>
              </div>
            </div>
          </div>
    </div>
    )
  }
}


export default BookList;

Book.js

import React, { Component } from 'react'

class Book extends Component {
  constructor(props) {
    super(props);
    this.props.updateParentState;
  }

  render() {
    return(
      <div className="book">
        <div key={this.props.book.title}>
          <div className="book-top">
            <div className="book-cover" style={{width:128, height:193, backgroundImage: `url(${this.props.book.imageLinks.thumbnail})`}}>
                  <div className="book-shelf-changer">
                    <select id="bookName" value={this.props.book.shelf}
                      onChange={(event) => this.props.handleShelfChange(this.props.book, event.target.value)}>
                      <option value="moveTo" disabled>Move to...</option>
                      <option value="currentlyReading">Currently Reading</option>
                      <option  value="wantToRead">Want to Read</option>
                      <option  value="read">Read</option>
                      <option value="none">None</option>
                    </select>

                  </div>
            </div>
          </div>
          <div className="book-title">{this.props.book.title}</div>
          <div className="book-authors">{this.props.book.authors}</div>
        </div>

  </div>
      )
  }
}

export default Book

所以,我有4个组件,如上图所示。从App component,我调用BookSearch组件,在其中我可以搜索书籍,并通过选择下拉列表中的值将书籍发送到App component。BookSearch组件中的每本书最初都会被分配一个书架属性“none”。当用户从BookSearch中选择书架值时,该书将自动添加到应用程序组件中。因此,当我从BookSearch导航回应用程序组件时,我应该能够看到分配书架中的书。因此,在这种情况下,我正在使用updateSearch函数。书籍通过具有下拉值的Book组件显示。

共有2个答案

危卜鹰
2023-03-14

在父组件构造函数中添加以下行:

this.updatethis.updateState.bind

更多https://reactjs.org/docs/handling-events.html

谢志用
2023-03-14

如果我理解正确,那么您正在修改函数updateState中的状态。

你应该做的是,

const updateState = (booksList) => {
   const books = [ ...this.state.books, ...booklist ];
   this.setState({ books });
}
 类似资料:
  • 假设我的父组件有两个子组件: 我从Child2获得一个输入,并将其传递给父组件(到目前为止,我知道该怎么做)。但是,我需要将该输入传递给Child1,以更新它的状态。 我怎么能那么做?

  • 我是reactjs的新手,我不知道如何从父组件中更改子组件的状态。下面是代码 每当对父组件中的执行时,我希望子组件接收。 有什么建议吗?

  • 问题内容: 假设我的父组件有两个子组件: 我从Child2获得输入,并将其传递给Parent组件(直到现在,我知道该怎么做)。但是然后我需要将该输入传递给Child1以更新其状态。 我怎样才能做到这一点? 问题答案: 希望您能得到主要想法-在Parent组件中创建一个函数,该函数将更改传递给Child1的值。ReactJS:为什么将组件的初始状态传递为prop是反模式?

  • 我有两个组件:父组件,我想改变子组件的状态: 和子组件: 我需要从父组件更改子组件的打开状态,或者当单击父组件中的按钮时,从父组件调用子组件的toggleMenu()?

  • 我有一个数组列表 记录在子组件中,它返回给我初始数组。 从API更改数据后 如果我在函数中将该数组记录在父组件中,我将得到一个对象数组。 它正在更改 ,但子组件没有。 我该怎么办??

  • 这个问题在这里已经得到了回答,但事情总是在变化。 基本上,父组件获取一些数据,子组件需要这些数据。 这是子组件。