我正在渲染通过映射在数组上创建的内容,该数组返回一个单独显示项目的数组。我正在使用商店中的索引位置来确定正在显示的卡。这很好用,但是当我实现一个onClick事件时,该事件从商店中获取当前使用的索引Im,然后使用商店中的索引将内容推入数组,事情开始崩溃。它返回初始索引值而不是当前索引值。由于我在实际的render方法中使用了索引值,因此它仅与onClick事件隔离,并且行为符合预期。我假设发生这种情况是因为当我在组件安装时在列表上进行映射时,它绑定了初始值的属性,而不传递更新的值吗?这是有问题的代码
//这是创建卡片列表的钩子
const [cardDeck, setCardDeck] = useState([])
useEffect(()=>{
renderCardArray();
},[props.news])
//这是调用动作创建者的功能
const addToList = () =>{
props.pushItemToReadingList(props.news[props.cardIndex]);
props.increaseCardIndex();
}
//这是设置为状态值的地图,我可以单独显示
const renderCardArray = () =>{
if(props.news.length > 1 && props.cardIndex < props.news.length){
setCardDeck(props.news.map((item,iter)=>{
return(
<div className="card" ref={drag} key={iter}>
<h3>{item.title}</h3>
<img src={item.urlToImage} alt='News' style={{maxWidth: '200px'}} />
<button onClick={props.increaseCardIndex}>X</button>
<button onClick={addToList}>{'<3'}</button>
</div>
)
}))`
// 2ed按钮每次单击返回的索引为0,但卡片在最终返回时将以正确的索引进行更新 //这是组件的最终返回值
return (
<div>
{cardDeck[props.cardIndex]}
</div>
)
}
//最后是connect和mapStateToProps
const mapStateToProps=(state)=>{
return {news: state.news, cardIndex: state.cardIndex}
}
export default connect(mapStateToProps,{
pushItemToReadingList,
increaseCardIndex
})(NewsCard);
如果有人可以帮助我理解为什么我执行addToList函数时没有收到其余组件正在接收的更新索引?还有一种更好的方法可以为映射列表提供更新的道具吗?(我已经暂时解决了这个问题,方法是切换动作创建者以不接受任何参数来推送,它只是在内部使用存储数据,但这对我没有帮助了解为什么会发生这种行为)(我也不打算使用本地状态和redux存储,我在这里将两者分开只是为了测试这种渲染和动画卡片的方法,而不必为我编写其他动作创建者和reducer cardDeck)
答案 0 :(得分:0)
您似乎在props.cardIndex
数组中缺少依赖项useEffect
,导致它在props.cardIndex
更新时不会更新:
useEffect(()=>{
if(props.news.length > 1 && props.cardIndex < props.news.length){
renderCardArray();
}
// renderCardArray depends on `props.cardIndex`, so
// make sure to add it here
},[props.news, props.cardIndex])
如果renderCardArray
的内容在useEffect
中是内联的,将更加清楚(除非您需要在其他地方调用该函数)。您还可以将news
和cardIndex
传递到renderCardArray
中,以更清楚地了解相关性。
renderCardArray(props.news, props.cardIndex);
我不确定这是否可以解决您的问题,但是这里有一些建议可以使代码更易于推理/调试:
为key
使用比索引更稳定的值。如果将元素添加到数组中或从数组中删除,则索引会更改,这可能会导致错误。如果item.title
对于每个项目都是唯一的,则可以使用它。
将数据设置为状态,并将JSX限制为从组件返回的内容。看起来您一次只需要渲染一张卡片,甚至可能不需要在本地状态下存储任何东西:
const item = props.news[props.cardIndex];
return (
<div className="card" ref={drag}>
<h3>{item.title}</h3>
<img src={item.urlToImage} alt='News' style={{maxWidth: '200px'}} />
<button onClick={props.increaseCardIndex}>X</button>
<button onClick={addToList}>{'<3'}</button>
</div>
)
如果要做需要保持一系列卡片状态,请保留数据而不是JSX,并在返回时映射cardDeck
数据:
const [cardDeck, setCardDeck] = useState([])
useEffect(()=>{
if(props.news.length > 1 && props.cardIndex < props.news.length){
setCardDeck(props.news);
}
},[props.news, props.cardIndex]);
...
return (
cardDeck.map(card => (
<div className="card" ref={drag} key={card.title}>
<h3>{card.title}</h3>
<img src={card.urlToImage} alt='News' style={{maxWidth: '200px'}} />
<button onClick={props.increaseCardIndex}>X</button>
<button onClick={addToList}>{'<3'}</button>
</div>
)
)
pushItemToReadingList
和increaseCardIndex
,您可以分派单个动作addItemToReadingList
,然后让reducer负责将其添加到存储的列表中并增加索引。