【问题标题】:React redux props undefined反应 redux 道具未定义
【发布时间】:2020-02-23 19:53:52
【问题描述】:

我是 redux 的新手,我发现很难找到一个既使用异步调用又使用 typescript 的好指南。我试图自己弄清楚,但我有点卡住了。如果有人可以查看我的代码并就如何解决这个问题给我反馈和/或建议,我将不胜感激!

// types.ts file
export const FETCH_USERS_REQUEST = 'FETCH_USERS_REQUEST';
export const FETCH_USERS_SUCCESS = 'FETCH_USERS_SUCCESS';
export const FETCH_USERS_FAILURE = 'FETCH_USERS_FAILURE';

^ 这里我定义了常量以保持一致性。

// userActions.ts
import { FETCH_USERS_FAILURE, FETCH_USERS_REQUEST, FETCH_USERS_SUCCESS } from './types';
import { Dispatch } from 'redux';
import axios, { AxiosResponse } from 'axios';

export interface UserProps {
  id: number
  name: string
  email: string
}

export const fetchUsersRequest = () => {
  return {
    type: FETCH_USERS_REQUEST,
  };
};

export const fetchUsersSuccess = (users: Array<UserProps>) => {
  return {
    type: FETCH_USERS_SUCCESS,
    users: users,
  };
};

export const fetchUsersFailure = (error: string) => {
  return {
    type: FETCH_USERS_FAILURE,
    error: error,
  };
};

export const fetchUsers = () => {
  return (dispatch: Dispatch): Promise<unknown> => {
    dispatch(fetchUsersRequest());
    return axios.get('https://jsonplaceholder.typicode.com/users')
      .then((response: AxiosResponse<UserProps[]>) => {
        dispatch(fetchUsersSuccess(response.data));
        return response.data;
      })
      .catch((error: string) => {
        dispatch(fetchUsersFailure(error));
      });
  };
};

用户减速器

import { UserProps } from '../actions/userActions';
import { FETCH_USERS_FAILURE, FETCH_USERS_REQUEST, FETCH_USERS_SUCCESS } from '../actions/types';

interface Action {
  type: string
  payload: Array<UserProps> | string,
}

export interface initialStateProps {
  loading: boolean,
  users: Array<UserProps>
  error: string
}

const initialState: initialStateProps = {
  loading: false,
  users: [],
  error: '',
};

export const userReducer = (state = initialState, action: Action) => {
  switch (action.type) {
    case FETCH_USERS_REQUEST:
      return {
        ...state,
        loading: true,
      };
    case FETCH_USERS_SUCCESS:
      return {
        loading: false,
        users: action.payload,
      };
    case FETCH_USERS_FAILURE:
      return {
        loading: false,
        users: [],
        error: action.payload,
      };
    default: {
      return state;
    }
  }
};

export const getUsers = (state: initialStateProps) => state.users;
export const getUsersRequest = (state: initialStateProps) => state.loading;
export const getUsersFailure = (state: initialStateProps) => state.error;

然后对于我的项目,我使用connected-router 来帮助跟踪路线。

import { combineReducers } from 'redux';
import { History } from 'history';
import { connectRouter } from 'connected-react-router';
import { userReducer } from './userReducers';

export const createRootReducer = (history: History) => combineReducers({
  router: connectRouter(history),
  userReducer,
});

商店:

import { createBrowserHistory } from 'history';
import { applyMiddleware, compose, createStore } from 'redux';
import thunkMiddleware from 'redux-thunk'
import { createLogger } from 'redux-logger';
import { routerMiddleware } from 'connected-react-router';
import { createRootReducer } from './reducers';

export const history = createBrowserHistory();

const loggerMiddleware = createLogger();

export const configureStore = (preloadedState?: any) => {
  const composeEnhancer: typeof compose = (window as any).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
  return createStore(
    createRootReducer(history),
    preloadedState,
    composeEnhancer(
      applyMiddleware(
        routerMiddleware(history),
        thunkMiddleware,
        loggerMiddleware,
      ),
    ),
  );
};

在应用程序中我使用这个:

const mapStateToProps = (state: initialStateProps) => ({
  error: getUsersFailure(state),
  users: getUsers(state),
  loading: getUsersRequest(state)
});

const mapDispatchToProps = (dispatch: Dispatch) => bindActionCreators({
  fetchUsers: fetchUsers
}, dispatch);

export default connect(
  mapStateToProps,
  mapDispatchToProps,
)(TopbarNav);

但是当我console.log(props); 我得到:

users: undefined

loading: undefined

error: undefined

编辑: 我在这里运行 fetchUsers:

const TopbarNav: React.FC = (props: any) => {

  const [loading, setLoading] = React.useState(true);

  const classes = useStyles();

  useEffect(() => {
    props.fetchUsers();
  });

  const handler = () => {
    console.log({props});
  };
};

我在这个问题中省略了渲染方法。

EDIT 2 更新了 useEffect 方法:

const [users, setUsers] = React.useState([]);

const [loading, setLoading] = React.useState(true);

const classes = useStyles();

useEffect(() => {
  setUsers(props.fetchUsers());
}, [users, props, loading]);

const handler = () => {
  console.log(props.loading);
};

【问题讨论】:

  • 你在哪里运行 fetchUsers()?
  • 内部使用效果
  • 您的代码看起来不错,也许我们遗漏了一些东西。处理这类事情的一种常见方法是隔离代码的每个组件。尝试将初始状态放入组件中,然后通过组件调用 redux 操作。
  • 好的,我该怎么做?可以举个例子吗?
  • 也许可以尝试通过 react 和 redux 扩展来调试。首先检查redux extension 以确保您调度操作并将数据保存到存储中。然后查看react extension,查看组件的props。 chrome.google.com/webstore/detail/redux-devtools/…chrome.google.com/webstore/detail/react-developer-tools/…

标签: reactjs redux react-redux redux-thunk react-props


【解决方案1】:

通过使用combineReducers,我认为您的状态将如下所示

{
  router: ...,
  userReducer: ...,
}

所以你可以通过修改选择器来寻找正确的道具来修复它

state.userReducer.users
state.userReducer.loading
...

【讨论】:

  • 这确实有效,但它会在 useEffect 方法中无休止地执行,即使我为该方法提供了一个包含道具和用户的数组。
  • @Ezrab_ 这些更改看起来不太好,您不需要用户和加载的本地状态,因为您已经在道具中拥有它们,尝试撤消它,只需调用 props.fetchUsers() useEffect,传递一个 empry 数组作为依赖项,因为它不依赖任何 prop 并将组件包装在 React.memo 中,无论您需要用户或从 props 加载使用它们:props.user,props.loading
  • 你能简单解释一下为什么将组件包装在 React.memo 中是一个合乎逻辑的选择吗?
  • @Ezrab_ 我认为这是必要的,因为你在执行每个渲染时遇到了 useEffect 问题,但如果你让它在没有它的情况下工作,我想没关系
猜你喜欢
  • 2018-09-16
  • 2022-01-11
  • 2021-08-21
  • 2020-12-01
  • 1970-01-01
  • 2018-09-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多