这是一本互动圣经。
在下面的代码中,我有一些按钮,这些按钮是根据我之前单击的按钮有条件地呈现的。
代码调用 API 来检索数据。
useEffect(() => {
dispatch(fetchBibleBooks());
}, [dispatch]);
useEffect(() => {
if(selectedBook && chapter){
dispatch(fetchBibleBookChapter( {selectedBook, chapter} ));
}
}, [dispatch, selectedBook, chapter]);
useEffect(() => {
setOTBooks(bibleArray.filter(book => book.testament === 'OT'));
}, [ clickedOT ]);
useEffect(() => {
setNTBooks(bibleArray.filter(book => book.testament === 'NT'));
}, [ clickedNT ]);
useEffect(() => {
setBookChapters(bibleArray.find(book => book.id === selectedBook)?.chapters || []);
}, [ selectedBook ]);
useEffect(() => {
bibleArray.filter(chapter => chapter);
const subsetBibleArray = bibleArray.map( text => text.cleanText );
setChapterText(subsetBibleArray);
});
return(
<Container>
<Row>
<Col style={{textAlign: 'center'}}>
<h1 style={{ color: 'darkblue'}}>Biblia Interactiva</h1>
<Button style={{margin: '2rem'}} color='warning' size='lg' onClick={() => setClickedOT(true)}>
Antiguo Testamento
</Button>{' '}
<Button style={{margin: '2rem'}} color='warning' size='lg' onClick={() => setClickedNT(true)}>
Nuevo Testamento
</Button>
</Col>
</Row>
<Row style={{marginTop:'4rem'}}>
<Col style={{textAlign:'left', marginLeft:'-18rem'}}>
{
clickedOT && otBooks.sort((b1, b2) => {
if (b1.order < b2.order) return -1;
if (b1.order > b2.order) return 1;
return 0;
}).map(book => (
<Button color='primary' key={book.order} style={{ margin: '4px' }} onClick={() => setSelectedBook(book.id)}>
{book.name}
</Button>
))
}
</Col>
<Col style={{textAlign:'left', marginRight:'-18rem'}}>
{
clickedNT && ntBooks.sort((b1, b2) => {
if (b1.order < b2.order) return -1;
if (b1.order > b2.order) return 1;
return 0;
}).map(book => (
<Button color='primary' key={book.order} style={{ margin: '4px' }} onClick={() => setSelectedBook(book.id)}>
{book.name}
</Button>
))}
</Col>
</Row>
<Row>
<Col style={{textAlign:'center', marginLeft:'', marginTop: '6rem'}}>
{
bookChapters.map(ch => (
<Button color='success' key={ch.id} style={{ margin: '4px' }} onClick={() => setChapter(ch.chapter)}>
{ch.chapter}
</Button>
)
)
}
</Col>
</Row>
<Row>
<Col style={{textAlign:'left', marginLeft:'', marginTop: '6rem'}}>
{
chapterText.map((text, idx) => (
<p key={idx}>
{text}
</p>
)
)
}
</Col>
</Row>
</Container>
)
}
代码第一次运行良好,但如果我重新单击其中一个圣经书按钮,先前渲染的章节按钮将消失,文本也会消失,这很好,但它应该将章节按钮重新渲染为新的点击相关书籍。
“selectedBook”变量已更新,但状态变量“chapter”仍保留前一章的值,因此新状态具有包含旧章节的新书,并从 API 中获取该章节,并且相关章节按钮不可用没有被渲染。
有两件事:
const onChangeBook = (id) => {
setSelectedBook(book.id);
setSelectedChapter(undefined); // undefined, or null, or similar
}
然后让所有按钮调用此函数
bookChapters
是由于选择(或不选择)一本书而计算/导出的,但它不是状态本身。const bookChapters = bibleArray.find(book => book.id === selectedBook)?.chapters || []
就是这样。它会在每次渲染时重新计算,这很好(除非您遇到性能问题)。您无需状态即可按住
bookChapters
。
chapterText
不太可能也是状态,它不应该是状态并且效果不应该存在。
看到这个你可能不需要效果