В React, как правильно использовать хуки для обновления одного компонента, когда я запускаю функцию Add в другом компоненте? - PullRequest
0 голосов
/ 23 марта 2020

Я создаю приложение для поиска книг, чтобы выучить React. Я не могу понять, как добавить книгу из моего списка всех («Список книг») в отдельный «Список чтения». У меня есть JSON файл данных о книгах, который выглядит следующим образом:

[
  {
    "descr": "Take a voyeuristic look at life in Sheffield...",
    "author": "Philip Hensher",
    "title_id": "9812",
    "title": "The Northern Clemency",
    "cover": "https://www.whichbook.net/assets/images/big/9812.jpg",
    "similar": "https://www.whichbook.net/#cmd=search&search-type=3&id=9812"
  },
  ...
]

, и я пролистываю их через oop в своем компоненте BookList. js для отображения каждой книги и кнопку «Добавить» в список чтения ", например, так:

export default function BookList ({ handleAddBook }) {
    return (
        <div>
            {BookData.map((book) => {
                return (
                <>
                    <BookDetail key={book.title_id} book={book} />
                    <button onClick={handleAddBook}>Add to Reading List</button>
                </>
                )
            })}
        </div>
    )
}

Для каждого BookDetail, я просто отображаю title и title_id. В BookDetail. js:

export default function BookDetail({ book }) {
    return (
        <div>
            <h1>{book.title}</h1>
            <p>{book.title_id}</p>
        </div>
    )
}

Это прекрасно работает. Я вижу список всех моих книг. Теперь в моем списке чтения js я пытаюсь выполнить l oop через книги, аналогичные моему BookList, за исключением того, что функциональный компонент имеет аргумент booksToRead:

export default function ReadingList({ booksToRead }) {
    return (
        <div>
            <h3>My Reading List</h3>
            {booksToRead.map((book) => {
                return (
                <>
                    <BookDetail key={book.title_id} book={book} />
                </>
                )
            })}
        </div>
    )
}

Хорошо, теперь давайте посмотрим на Приложение. js, где я пытался решить это. В основном я пытаюсь использовать useState() и useEffect() для обновления моего booksToRead массива всякий раз, когда константа newBookToRead изменяется, что обрабатывается в функции handleAddBook. Я инициализировал booksToRead с фиктивными данными, и он отображается в браузере, но никогда не обновляется.

function App() {

    const [books, setBooks] = useState([])
    const [booksToRead, setBooksToRead] = useState([{ title: 'initialBookToRead', title_id: '1234' }])
    const [newBookToRead, setNewBookToRead] = useState([{ title: 'addMe', title_id: '000' }])

    function handleAddBook() {
        setNewBookToRead(newBookToRead)
    }

    useEffect(() => {
        setBooksToRead(booksToRead => [...booksToRead, newBookToRead])
    }, [newBookToRead])


  return (
    <main>
        <BookList books={books} />
        <ReadingList booksToRead={booksToRead} />
    </main>
  );
}

export default App;

Я попытался переместить логи c на другие компоненты, я пытался создать ReadingListContext с createContext и использованием ReadingListContext.Provider value={booksToRead} вместо тега <ReadingList>, я просто не могу понять это.

Кроме того, моя консоль потенциально дает мне Warning: Each child in a list should have a unique "key" prop. для обоих BookList и ReadingList, хотя я установил ключ на book.title_id, который является уникальным кодом. ????

1 Ответ

1 голос
/ 23 марта 2020
export default function BookList ({ books, handleAddBook }) {
return (
    <div>
        {books.map((book) => {
            const onAddBook = () => handleAddBook(book);
            return (
            <>
                <BookDetail key={book.title_id} book={book} />
                <button onClick={onAddBook}>Add to Reading List</button>
            </>
            )
        })}
    </div>
)
}

function App() {

    const [books, setBooks] = useState([])
    const [booksToRead, setBooksToRead] = useState([{ title: 'initialBookToRead', title_id: '1234' }])

    function handleAddBook(book) {
        setBooksToRead([...booksToRead, book])
    }


  return (
    <main>
        <BookList books={books} handleAddBook={handleAddBook}/>
        <ReadingList booksToRead={booksToRead} />
    </main>
  );

}

export default App;

Пожалуйста, используйте вышеуказанные компоненты. Вам нужно передать book в качестве параметра для обработки AddBook. Нет необходимости хранить newBookToRead и использовать эффект. Вы можете использовать handleAddBook, как уже упоминалось.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...