【问题标题】:How to dispatch an redux action to load data inside useEffect on page load如何在页面加载时调度 redux 操作以在 useEffect 中加载数据
【发布时间】: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 是否工作正常。

标签: reactjs redux react-hooks


【解决方案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,现在可以在没有mapStateToPropsmapDispatchToProps 的情况下编写。

      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();带括号,效果很好。真是个疯子。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-03-25
      • 1970-01-01
      • 2018-05-21
      • 1970-01-01
      • 1970-01-01
      • 2018-12-04
      • 2016-06-26
      相关资源
      最近更新 更多