如何避免在React.js中使用useState钩子来更新函数组件的所有实例?

时间:2020-03-25 22:35:54

标签: javascript reactjs react-hooks instance react-component

TL; DR我正在制作一个可重用的Button功能组件。我的按钮标签的useState()钩子正在每个Button实例中进行更新。我该如何预防?

我对React和构建Book Finder应用程序很陌生,以便学习。到目前为止,我的应用程序有一个BookList和一个ReadingList。任一列表中的每个BookDetail都有一个Button,可以从ReadingList中添加/删除该书。添加/删除功能可以正常运行,但使用useState更新Button的标签将更新Button组件的每个实例,而不仅仅是单击的那个实例。 / p> Buttons中的书上的

BookList以标签“添加到阅读列表”开头,但是如果我点击其中的任何,则全部其中的更新为“从阅读列表中删除”。

我尝试将逻辑移到Button组件或List组件中,但是最终我破坏了该函数。

App.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 :(得分:0)

您能否进行这些更改,并让我知道是否有任何进展?

  1. ImageView
  2. onTouchListener

好像在<Button label={label} onClick={() => addOrRemove(book)} />中,您传递的是<button className='btn' onClick={onClick}>而不是button作为函数参数

答案 1 :(得分:0)

目前,您要声明一个标签,并在所有书籍条目中使用相同的标签。这就是为什么它们都显示相同的标签的原因。您需要跟踪每本书的标签,例如通过将标签保留为book对象中的字段。

例如:

a = symbols('a')
print(f[0].subs({x: 7, y: 8}))
print(f[1].subs({x: a, y: a + 4}))
print(f[2].subs({x: 2*a, y: 3*a + 5}))

然后:

23
6*a + 16
24*a + 30

这样,每本书都有自己的标签。