Как я могу избежать обновления всех экземпляров моего функционального компонента с помощью ловушки useState в React. js? - PullRequest
0 голосов
/ 26 марта 2020

TL; DR Я создаю компонент многократного использования Button. Мой useState() хук для метки кнопки обновляется каждый экземпляр Button. Как я могу предотвратить это?

Я очень новичок в React и создаю приложение Book Finder для обучения. Пока что мое приложение имеет BookList и ReadingList. Каждый BookDetail в любом списке имеет Button для добавления / удаления этой книги из ReadingList. Функция добавления / удаления работает (phew), но использование useState для обновления метки Button обновляет каждый экземпляр компонента Button, а не только тот, который был нажат.

Buttons для книг в BookList начинаются с метки «Добавить в список чтения», но если я нажму любой из них, все из них обновятся до «Удалить из списка чтения» .

Я пытался переместить логи c в компонент Button или в компонент List, но я просто нарушил функцию.

Приложение. js

function App() {

const books = useState([])
const [booksToRead, setBooksToRead] = useState([])
const [addRemove, setAddRemove] = useState(true)
const [label, setLabel] = useState('Add to Reading List')

function handleAddBook(book) {
    const newID = book.title_id
    if( (typeof booksToRead.find(x => x.title_id === newID)) == 'undefined' ) {
        setBooksToRead([...booksToRead, book])  
    }
}

function handleRemoveBook(book) {
    console.log(book)
    const array = booksToRead
    const index = array.indexOf(book)
    const newArray = [...array.slice(0, index), ...array.slice(index +1)]
    setBooksToRead(newArray)
}

function addOrRemove(book) {
    if( addRemove ) {
        handleAddBook(book)
        setLabel('Remove from Reading List')
        setAddRemove(false)
    } else {
        handleRemoveBook(book)
        setLabel('Add to Reading List')
        setAddRemove(true)
    }
}

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

export default App;

BookList. js

function BookList ({ book, label, handleAddBook, addOrRemove }) {

    return (
        <div className="booklist">
            {BookData.map((book, index) => {

                const onAddBook = () => addOrRemove(book)

                return (
                <div key={index} className="card">
                    <BookDetail key={book.title_id} book={book} />
                    <Button key={index + 'btn'} label={label} onClick={onAddBook} />
                </div>
                )
            })}
        </div>
    )
}

export default BookList

И, наконец, Button. js

export default function Button({ styleClass, label, onClick }) {

    return (
        <button className='btn' onClick={(event) => onClick(event)}>
            {label}
        </button>
    )
}

Пример без стилей в codeandbox: https://codesandbox.io/s/cool-rgb-fksrp

Ответы [ 2 ]

0 голосов
/ 26 марта 2020

Как сейчас, вы объявляете одну метку и используете ее для всех своих записей в книге. Вот почему они все отображают одну и ту же метку. Вам нужно будет отслеживать метку каждой книги, например, сохраняя метку как поле в объекте книги.

Например:

const books = useState([{ label: 'Add to reading list', addRemove: true }])

И затем:

function addOrRemove(book) {
    if( book.addRemove ) {
        handleAddBook(book)
        book.label = 'Remove from Reading List'
        book.addOrRemove = false
    } else {
        handleRemoveBook(book)
        book.label = 'Add to Reading List'
        book.addOrRemove = true
    }
}

Таким образом, каждая книга имеет свой собственный ярлык.

0 голосов
/ 26 марта 2020

Можете ли вы внести эти изменения и сообщить мне, если есть какой-либо прогресс:

  1. <Button label={label} onClick={() => addOrRemove(book)} />
  2. <button className='btn' onClick={onClick}>

Похоже что в button вы передаете event вместо book в качестве параметра функции

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