我有一个组件,我将 API 响应存储在 responseArray
中,我正在使用此 responseArray
使用钩子初始化 matchFundResults
状态。接下来,我尝试使用 matchFundResults
作为依赖项运行 useEffect,但 matchFundResults
始终为空白,而我在 responseArray
中有值。这应该如何解决?
const MatchFundModal = ({ row, val }) => {
let rightBody;
const dispatch = useDispatch();
const selectedRows = useSelector((state) => state.pcPerformance.processor.checkedRows.selectedRows || []);
const responseArray = useSelector((state) => state.pcPerformance.processor.fundAliases);
const [showMatchFundModal, setshowMatchFundModal] = useState(val);
const [matchFundResults, setMatchFundResults] = useState(responseArray);
const [activeRowData, setActiveRowData] = useState({ Id: null, FundName: null, SourceId: null });
const [selectedMatchFund, setSelectedMatchFund] = useState();
const [searchFieldVal, setSearchFieldVal] = useState();
if (!activeRowData.Id) {
const firstRow = selectedRows.length > 0 && selectedRows[0];
setActiveRowData({ Id: firstRow.Id, FundName: firstRow.FundName, SourceId: firstRow.SourceId });
//dispatch(getFundNameAliasMatch(firstRow.FundName, firstRow.SourceId));
}
useEffect(() => {
dispatch(getFundNameAliasMatch(activeRowData.FundName, activeRowData.SourceId));
}, [activeRowData.Id]);
console.log('Helloworld responseArray', responseArray);
console.log('Helloworld matchFundResults', matchFundResults);
useEffect(() => {
rightBody = matchFundResults**.map((item) => {
return (
<li key={item.FundId}>
<input
type="radio"
value={item.FundId}
name="action-radio"
id={`action-radio-${item.FundId}-${item.SourceId}`}
onClick={(e) => handleRadioButtonClick(e)}
/>
<span>{item.FundName}</span>
<br />
<span className="searchFundID">#{item.FundId}</span>
</li>
);
});
}, [matchFundResults, activeRowData.Id]);
const matchFundBody = (
<div className="matchFundModal grid">
<p className="matchFundModal__header 12">Match or add</p>
<div className="matchFundModal__body 12">
<div className="matchFundModal__body__right 6">
<p id="possibleMatchText">Possible matches</p>
<ul>{rightBody}</ul>
</div>
</div>
<div className="matchFundModal__footer 12">
<button className="matchFundModal__footer__button">Match Selected</button>
</div>
</div>
);
return (
<Fragment>
<Modal
isOpen={showMatchFundModal}
bodyContent={matchFundBody}
showHeader={false}
handleOnModalToggleFunction={hideModal}
handleOnModalPrimaryButtonClick={onPrimaryButtonClick}
handleOnModalSecondaryButtonClick={hideModal}
primaryButtonText={'Match Fund'}
centered={true}
size="sm"
hideFooterButtons={true}
modalClasses="matchFundModal"
showFooter={false}
/>
</Fragment>
);
};
export default MatchFundModal;```
[![enter image description here][1]][1]
[1]: https://i.stack.imgur.com/HxIv4.png
答案 0 :(得分:1)
我不知道您为什么要将 responseArray 复制到 matchFundResults 而不是直接使用 responseArray 但是当 responseArray 更改时您从不使用 setMatchFundResults 所以您只在最初设置它并且那时 responseArray 可能是一个空数组。您可以执行以下操作:
const responseArray = useSelector((state) =>
state.pcPerformance.processor.fundAliases);
const [matchFundResults, setMatchFundResults] = useState(responseArray);
//every time responseArray changes you need to set matchFundResults
useEffect(()=>setMatchFundResults(responseArray),[responseArray])
但最好不要将 redux 状态复制到本地状态,而是直接使用 redux 状态。
您的评论表明您拥有处于 redux 状态的所有数据并且想要过滤数据(您将 redux 状态复制到本地状态的原因)。您可以通过以下方式使用选择器做到这一点:
const { Provider, useSelector } = ReactRedux;
const { createStore } = Redux;
const { createSelector } = Reselect;
const { useState, useMemo } = React;
const initialState = {
data: [
'hello world',
'hello redux',
'hello react',
'goodbye jquery',
],
};
const reducer = (state) => state;
//selectors
const selectData = (state) => state.data;
const createSelectFilteredData = (filter) =>
createSelector([selectData], (data) =>
data.filter((item) =>
item.toLowerCase().includes(filter.toLowerCase())
)
);
//creating store with redux dev tools
const store = createStore(reducer, initialState);
const App = () => {
const [filter, setFilter] = useState('');
const selectFilteredData = useMemo(
() => createSelectFilteredData(filter),
[filter]
);
const filteredData = useSelector(selectFilteredData);
return (
<div>
<label>
filter:
<input
type="text"
value={filter}
onChange={(e) => setFilter(e.target.value)}
/>
</label>
<div>
filtered data:
<pre>
{JSON.stringify(filteredData, undefined, 2)}
</pre>
</div>
</div>
);
};
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.0.5/redux.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/7.2.0/react-redux.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/reselect/4.0.0/reselect.min.js"></script>
<div id="root"></div>