React中从Redux数组筛选单条发票数据如何避免返回undefined获取数组结果
问题原因
Array.find()本身只会返回匹配的对象或者undefined,不符合你需要数组格式返回值的要求;- 直接替换为
Array.filter()出现无限打印/渲染的原因是:filter每次执行都会返回新的数组引用,而useSelector默认用引用相等判断值是否变化,所以每次都会触发组件重渲染,进而触发useEffect执行setInvoiceData,再次触发重渲染,形成死循环。
解决方案
方案1:改造useSelector返回逻辑(推荐)
直接在selector中处理find的结果,搭配浅比较避免不必要的重渲染,完全符合你的返回值要求:
首先导入react-redux提供的浅比较工具:
import { useSelector, shallowEqual } from 'react-redux';
修改selector的写法,同时可以删掉冗余的本地state和useEffect逻辑(不需要多存一层状态,直接用selector返回值即可),修改后的完整代码如下:
import React from 'react' import { Link } from 'react-router-dom' import backIcon from '../assets/images/icon-arrow-left.svg' import InvoiceDetailsHeader from './InvoiceDetailsHeader'; import { useSelector, shallowEqual } from 'react-redux'; import InvoiceCardDetails from './InvoiceCardDetails'; const InvoiceDetails = (props) => { const id = props.match.params.id; // 直接获取符合格式要求的数据:匹配到返回单元素数组,未匹配返回空数组 const invoiceData = useSelector((state) => { const target = state.invoices.find(invoice => invoice._id === id); return target ? [target] : []; }, shallowEqual); // 加浅比较,数组内容不变就不会触发重渲染 return ( <div className="mx-auto px-12 py-16 w-full max-w-3xl"> <Link to="/" className="text-neutral text-xs"><img className="inline -mt-1 mr-4" src={backIcon} alt="back" /> Go back</Link> <InvoiceDetailsHeader data={invoiceData} /> <InvoiceCardDetails data={invoiceData} /> </div> ) } export default InvoiceDetails
方案2:坚持用filter的修复方式
如果你一定要用filter实现需求,只要给useSelector加上浅比较参数即可解决无限渲染问题,效果和方案1完全一致:
const invoiceData = useSelector( (state) => state.invoices.filter(invoice => invoice._id === id), shallowEqual );
内容的提问来源于stack exchange,提问作者r121
相关产品推荐
相关产品推荐

