如何表明" loading"使用redux

时间:2015-12-12 03:32:04

标签: reactjs redux

假设我有一个如下所示的redux模块:

import fetch from 'isomorphic-fetch';

// CONSTANTS
const LOAD = 'LOAD';
const LOAD_SUCCESS = 'LOAD_SUCCESS';

// REDUCER
const initialState = { loading: false, data: [] };

export default function reducer(state = initialState, action) {
  switch (action.type) {
    case LOAD: return { ...state, loading: true };
    case LOAD_SUCCESS: return { ...state, loading: false, data: action.data };
    default: return state;
  }
}

// ACTION CREATORS
function requestLocations() {
  return { type: LOAD };
}

function receiveLocations(json) {
  return { type: LOAD_SUCCESS, data: json };
}

export function fetchLocations() {
  return function (dispatch) {
    dispatch(requestLocations());

    return fetch('http://myurl')
      .then(response => response.json())
      .then(json => dispatch(receiveLocations(json)));
  };
}

如果我在componentWillMount中进行异步调用,我会在第一次渲染时遇到loading状态。想象一下,我的组件看起来像这样(简化为简洁):

export default class LocationContainer extends React.Component {
  componentWillMount() {
    fetchLocations(); // already bound and injected via connect.
  }

  render() {
    const { loading, data } = this.props; // injected via connect from reducer above.
    if (loading) {
      return <Spinner />;
    } else {
      return <LocationExplorer locations={ data } />;
    }
  }
}

我遇到的问题是,在第一次呈现LocationContainer时,loading为false,而data尚未提取。在componentWillMount中,LOAD操作被触发,并且设置为true的loading的道具更改排队等待后续渲染。与此同时,在我第一次渲染时,LocationExplorer会在我真正想要Spinner时呈现,因为loading仍然是假的。我想知道如何在不设置firstRender = true状态变量hack的情况下解决这个问题。

3 个答案:

答案 0 :(得分:6)

一个选项可能是使用loading初始状态扩展您的data条件:

const initialState = { loading: false, data: [] };

如果您loadingdata为空,则表示您处于等待新数据到达的确切状态:

if (loading && data.length === 0) {
  return <Spinner />;
} else {

另外,我通常将异步调用放在componentDidMount而不是componentWillMount

答案 1 :(得分:0)

请勿在{{1​​}}中提出请求。相反,在安装组件之前执行此操作。 e.g。

componentWillMount

答案 2 :(得分:0)

除了可接受的答案外,我们一直在使用的另一种获得巨大成功的解决方案是在reducer上添加一个complete布尔值标志,如果响应在某个时候返回,我们将其标记为true。如果响应实际上返回一个空数组,这会使事情更加明确。 complete标志让我知道响应是来自服务器的,而不仅仅是我的初始状态。

if(loading && !complete) {
  return <Spinner />;
} else {
  return <Component data={data} />;
}

我认为我会添加它,以防对他人有所帮助。