>我正在尝试创建一个允许检测 redux 存储中更改的组件。在存储中设置 shouldUpdateData 标志后,负责更新的组件应使用异步操作创建程序提取数据。就我而言,要么发生错误"已达到最大更新数",要么更新从未发生。
根据调度函数 stopFetching()(关闭 shouldUpdateData 标志),错误或结果会发生变化。如果我在动作创建器内部进行调度,则有无穷无尽的更新。如果按如下所示使用代码,则不会进行更新。
我使用来自"react-redux"的useSelector()钩子的原因是检测加载属性的存储中的更改。
提前谢谢你。
这是动作创建者:
export function updateDataAsync(id) {
return function (dispatch) {
// dispatch(fetchDataRequest());
return fetch(`/api/user/${id}/data`, {
method: "GET",
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
})
.then(res => res.json())
.then(
(result) => {
let {projects, notes} = result;
// New data and dispatch function
dispatch(fetchDataSuccess({projects, notes}));
},
(error) => { dispatch(fetchDataFailure(error)) }
)
}
}
下面是此操作创建器的化简器:
export function savedData(state = DATA_INITIAL_STATE, action) {
switch(action.type) {
case FETCH_STATES.FETCH_DATA_REQUEST:
return {
...state,
loading: true
}
case FETCH_STATES.FETCH_DATA_SUCCESS:
return {
loading: false,
data: action.data,
error: ''
}
case FETCH_STATES.FETCH_DATA_FAILURE:
return {
loading: false,
data: {},
error: action.error.message
}
default:
return state;
}
}
正在执行更新的 React 组件:
function StoreUpdater({ update, userId, shouldUpdate, startFetch, stopFetch, children }) {
const loading = useSelector(state => state.savedData.loading);
let reqSent = useRef(false);
useEffect(()=>{
if(!reqSent && shouldUpdate) {
startFetch();
update(userId)
reqSent.context = true;
}
})
return loading ? <LoadingAnimation /> : children;
}
const mapStateToProps = (state) => {
return {
userId: state.user.id,
shouldUpdate: state.shouldUpdateData // The flag that should trigger the update
}
}
const mapDispatchToProps = (dispatch) => {
return {
stopFetch: () => { dispatch(setShouldFetchData(false)) },
update: (id) => { dispatch(updateDataAsync(id)) },
startFetch: () => dispatch(fetchDataRequest()),
}
}
export default connect(mapStateToProps, mapDispatchToProps)(StoreUpdater);
你不会将任何依赖项传递给useEffect
,因此它将在每个导致无限渲染的render
上调用
将useEffect
更改为
useEffect(()=>{
if(!reqSent && shouldUpdate) {
startFetch();
update(userId)
reqSent.context = true;
}
},[])
有关useEffect
的完整信息,请参阅此链接
我在负责更新的组件中创建的引用导致了问题。引用由于 if 语句为 false,导致更新调度发生。
mapStateToProps
和mapDispatchToProps
react-redux
高阶函数,用于将类组件connect
到存储中。 功能组件的等式是useSelector
和useDispatch
。 将 HOC reux 适配重写为钩子,并在useEffect
使用中添加 [ 依赖项 ]
function StoreUpdater({ update, userId, shouldUpdate, startFetch, stopFetch, children }) {
const loading = useSelector(state => state.savedData.loading);
const userId = useSelector(state => state.user.id);
const shouldUpdate = useSelector(state => state.shouldUpdateData);
let reqSent = useRef(false);
const dispatch = useDispatch() // import from 'react-redux'
useEffect(()=>{
if(!reqSent && shouldUpdate) {
dispatch(startFetch());
dispatch(update(userId));
reqSent.context = true;
}
}, [reqSent, shouldUpdate, startFetch, dispatch, update, userId])
return loading ? <LoadingAnimation /> : children;
}
export default StoreUpdater ;