如何在页面加载时调度 redux 操作以在 useEffect 中加载数据
Posted
技术标签:
【中文标题】如何在页面加载时调度 redux 操作以在 useEffect 中加载数据【英文标题】:How to dispatch an redux action to load data inside useEffect on page load 【发布时间】:2019-09-02 04:08:18 【问题描述】:我正在尝试将 redux 集成到现有的 react 应用程序中。我正在学习redux。我正在使用钩子。在互联网上有很多使用类组件的例子。我找不到如何使用功能组件实现此目的的示例。
下面的代码不会抛出错误。但是,useEffect
内部的动作没有被调用。该代码不产生任何输出。我想知道电话是否正确。有什么帮助吗?
Index.js
const store = createStore(rubricReducer, applyMiddleware(thunk));
ReactDOM.render(
<BrowserRouter basename=baseUrl>
<Provider store=store > <App /> </Provider>
</BrowserRouter>,
rootElement);
Rubrics.tsx
const mapStateToProps = state => (
rubrics: state.rubrics.items,
loading: state.rubrics.loading,
error: state.rubrics.error
);
const mapDispatchToProps = (dispatch) =>
return
getRubrics: () => dispatch(fetchRubrics())
;
const Rubrics = (props) =>
const rubrics, loading, error = props;
useEffect(() =>
props.dispatch(fetchRubrics());
, []);
if (error) return <div>Error! error.message</div>;
if (loading) return <div>Loading...</div>;
return (
<ul>
<React.Fragment>
rubrics.map(rubric =>
return (
<li key=rubric.id>rubric.title</li>
);
)
</React.Fragment>
</ul>
)
export default connect(mapStateToProps, mapDispatchToProps)(Rubrics);
rubricActions.tsx:
export function fetchRubrics()
return dispatch =>
dispatch(fetchRubricsBegin());
axios.get("api/Rubric/Index")
.then(response =>
console.log('success: reading rubrics');
dispatch(fetchRubricsSuccess(response.data));
return response.data;
)
.catch(error => fetchRubricsFailure(error) );
;
export const FETCH_RUBRICS_BEGIN = "FETCH_RUBRICS_BEGIN";
export const FETCH_RUBRICS_SUCCESS = "FETCH_RUBRICS_SUCCESS";
export const FETCH_RUBRICS_FAILURE = "FETCH_RUBRICS_FAILURE";
const fetchRubricsBegin = () => (
type: FETCH_RUBRICS_BEGIN
)
const fetchRubricsSuccess= (rubrics) => (
type: FETCH_RUBRICS_SUCCESS,
payload: rubrics
)
const fetchRubricsFailure = (error) => (
type: FETCH_RUBRICS_FAILURE,
payload: error
)
rubricReducer.tsx:
import
FETCH_RUBRICS_BEGIN,
FETCH_RUBRICS_SUCCESS,
FETCH_RUBRICS_FAILURE
from '../_actions/rubricActions';
const initialState =
rubrics: [],
loading: false,
error: null
;
const rubricReducer = (state = initialState, action) =>
switch (action.type)
case FETCH_RUBRICS_BEGIN:
return
...state,
loading: true,
error: null
;
case FETCH_RUBRICS_SUCCESS:
return
...state,
loading: false,
items: action.payload.rubrics
case FETCH_RUBRICS_FAILURE:
return
...state,
loading: false,
error: action.payload.error,
items: []
;
default:
return state;
export default rubricReducer;
【问题讨论】:
useEffect
对我来说看起来不错。您可能想检查fetchRubrics
是否工作正常。
【参考方案1】:
在您的调度映射中,您有
const mapDispatchToProps = (dispatch) =>
return
getRubrics: () => dispatch(fetchRubrics())
;
所以不要调用props.dispatch(fetchRubrics());
只需调用props.getRubrics()
或从道具中解构此方法
const rubrics, loading, error, getRubrics = props;
只需拨打getRubrics()
【讨论】:
FETCH_RUBRICS_BEGIN
动作是否被调度?这也可能是一个愚蠢的问题,但我假设您使用 redux-thunk 或任何类似的中间件?【参考方案2】:
下面是正确的代码:
const Rubrics = (props) =>
useEffect(() =>
props.fetchAllRubrics();
, [])
return (
props.rubrics.map((rubric) =>
return (<RubricCard rubric=rubric />)
)
)
const mapStateToProps = state => (
error: state.error,
rubrics: state.rubrics,
loading: state.oading
)
const mapDispatchToProps = dispatch =>
return fetchAllRubrics: () => dispatch(fetchRubricsData())
export default connect(
mapStateToProps,
mapDispatchToProps
)(Rubrics);
【讨论】:
【参考方案3】:这里的问题是您使用了不正确的 mapDispatchToProps。你不需要显式设置 dispatch 函数,这就是 react redux 为你做的。
所以,下面是正确的做法:
// Now you won't be creating a new object every time your component re-renders
const mapDispatchToProps =
getRubrics: fetchRubrics
const Rubrics = (props) =>
const getRubrics = props;
// You should always add elements inside your render scope
// to the second array parameter of useEffect to prevent unexpected bugs.
useEffect(() =>
getRubrics();
, [getRubrics]);
return (
<div>Your component here!</div>
)
【讨论】:
【参考方案4】:使用自 v7.1.0 起由react-redux 提供的hooks,现在可以在没有mapStateToProps
和mapDispatchToProps
的情况下编写。
import React, useEffect from 'react';
import useDispatch, useSelector from 'react-redux';
const Rubrics = () =>
const dispatch = useDispatch();
const rubrics, loading, error = useSelector(
state => (
error: state.error,
rubrics: state.rubrics,
loading: state.loading
)
);
useEffect(() =>
dispatch(fetchRubrics());
, [dispatch]);
if (error) return <div>Error! error.message</div>;
if (loading) return <div>Loading...</div>;
return (
<ul>
<React.Fragment>
rubrics.map(rubric =>
return (
<li key=rubric.id>rubric.title</li>
);
)
</React.Fragment>
</ul>
)
;
【讨论】:
明智的做法是 useEffect 包含 dispatch 作为依赖项 您知道,我在编码const dispatch = useDispatch;
时遇到了错误,并且出现了“无效的挂钩调用”错误。刚刚编码了```const dispatch = useDispatch();带括号,效果很好。真是个疯子。以上是关于如何在页面加载时调度 redux 操作以在 useEffect 中加载数据的主要内容,如果未能解决你的问题,请参考以下文章
使用 React-Router 和 Redux 时单击链接时如何调度操作?
如何在 getInitialProps 中使用 redux 钩子
使用 TypeScript 在 Chrome 扩展背景页面中调度 Redux 操作