getState 函数在 action creator 中的调用总是 returns 空数组

getState function call in action creator always returns empty array

正在从组件“UserHeader”的多个实例中对操作创建者“fetchUser”进行多次调用。每次调用都应该向商店添加一个用户。在动作创建器“fetchUser”中,一个 console.log 语句用于显示使用“getState”函数添加的用户列表。第一次调用会将用户列表显示为空,但后续调用应该显示一些用户。我不知道为什么“getState”函数总是 returns 一个空数组。请帮忙解决这个问题。代码托管在 codesandbox

动作创作者

export const fetchUser = id => async (dispatch, getState) => {
    
  console.log(getState()); // Always empty array

  const response = await jsonPlaceholder.get(`/users/${id}`); // call to external API using Axios

  dispatch({ type: 'FETCH_USER', payload: response.data });

};

减速器

export default (state = [], action) => {
  switch (action.type) {
    case 'FETCH_USER':
      return [...state, action.payload];
    default:
      return state;
  }
};

UserHeader

import React from 'react';
import { connect } from 'react-redux';
import { fetchUser } from '../actions';

class UserHeader extends React.Component {
  componentDidMount() {
    this.props.fetchUser(this.props.userId); // call to action creator
  }

  render() {
    const user = this.props.users.find(user => user.id === this.props.userId);

    if (!user) {
      return null;
    }

    return <div className="header">{user.name}</div>;
  }
}

const mapStateToProps = state => {
  return { users: state.users };
};

export default connect( mapStateToProps, { fetchUser } )(UserHeader);

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';

import App from './components/App';
import reducers from './reducers';

const store = createStore(reducers, applyMiddleware(thunk));

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.querySelector('#root')
);

Link to image that shows zero Users

您 运行 在 forEach 中创建了一个 API 请求..迭代不会等到上一次迭代完成,这就是您的商店尚未更新的原因。 如果你愿意安慰:

export const fetchUser = (id) => async (dispatch, getState) => {
  console.log("before:", getState());
  const response = await jsonPlaceholder.get(`/users/${id}`);
  dispatch({ type: "FETCH_USER", payload: response.data });
  console.log("after:", getState());
};

你会看到:

before: (->users don't contain values)
before: (->users don't contain values)
...
after: (->users contain values)
after: (users contain values
..

所以,基本上你需要在每次迭代后等待。

这是我使用 this article 实现的(我也使用 mapfilter func 而不是 lodash func ,但这由您决定):

async function asyncForEach(array, callback) {
  for (let index = 0; index < array.length; index++) {
    await callback(array[index], index, array);
  }
}

export const fetchPostsAndUsers = () => async (dispatch, getState) => {
  await dispatch(fetchPosts());

  const postsUsersIds = getState().posts.map((ele) => ele.userId);
  const uniqueVal = postsUsersIds.filter(
    (t, i) => postsUsersIds.indexOf(t) === i
  );

  asyncForEach(uniqueVal, async (val) => {
    await dispatch(fetchUser(val));
  });
};

现在 fetchUser func 中的值已更新,您也可以在 sandbox

中看到代码