javascript - React-Redux:如何使用异步调用中的数据填充组件的加载属性?

标签 javascript reactjs asynchronous redux react-redux

我有一个自动完成组件,它将一组术语作为 dataSource 属性。我想要输入的数据位于公共(public) API 中,并且我已按照教程 here 进行操作。获取下面的代码。但是本教程(以及许多其他教程)解释了如何将这些操作绑定(bind)到事件,而我想用页面加载时的数据填充此 Prop 。我该如何去做呢?

actions.js

import fetch from 'isomorphic-fetch';

export function loadSchools(termId) {
  return {
    type: 'LOAD_SCHOOLS',
    termId
  };
}

export function receiveSchools(termId, json) {
  return {
    type: 'RECEIVE_SCHOOLS',
    termId,
    schools: json.data.children.map(child => child.data), // ???
    receivedAt: Date.now()
  };
}

export function getSchools(termId) {
  return function (dispatch) {
    dispatch(loadSchools(termId));
    return fetch('http://www.northwestern.edu/class-descriptions/4650/index-v2.json')
      .then(response => {
        if (response.status >= 400) {
          throw new Error('Bad response from server');
        }
        return response.json();
      })
      .then(data => dispatch(receiveSchools(termId, data)));
  };
}

reducers.js

const initialState = {
  schoolsData: {
    isFetching: false,
    lastUpdated: 0,
    schools: []
  }
};

function schools(state = initialState, action) {
  switch (action.type) {
    case 'LOAD_SCHOOLS':
      return {
        ...state,
        isFetching: true
      };
    case 'RECEIVE_SCHOOLS':
      return {
        ...state,
        isFetching: false,
        schools: action.schools,
        lastUpdated: receivedAt
      }
    default:
      return state;
  }
}

export default schools;

Search.jsx

import React from 'react';
import AutoComplete from 'material-ui/AutoComplete';

export default class Search extends React.Component {
  render() {
    return (
        <AutoComplete
          hintText="Search for something."
          dataSource={this.props.searchdata}
          maxSearchResults={15}
          filter={AutoComplete.caseInsensitiveFilter}
          onNewRequest={}
        />
    );
  }
}

Search.propTypes = {
  searchdata: React.PropTypes.array.isRequired,
  onSelect: React.PropTypes.func
};

index.jsx

import 'babel-polyfill';
import React from 'react';
import ReactDOM from 'react-dom';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import { grey500, white, fullBlack } from 'material-ui/styles/colors';
import { fade } from 'material-ui/utils/colorManipulator';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
import thunkMiddleware from 'redux-thunk';
import schools from './reducers/reducers';
import colors from './colors';
import NavBar from './components/NavBar.jsx';
import Serif from './components/Serif.jsx';

const store = createStore(schools, applyMiddleware(thunkMiddleware));

const muiTheme = getMuiTheme({
  palette: {
    primary1Color: colors.northwesternPurple,
    primary2Color: colors.northwesternPurple120,
    primary3Color: grey500,
    accent1Color: colors.northwesternPurple30,
    accent2Color: colors.richBlack10,
    accent3Color: colors.richBlack50,
    textColor: colors.richBlack80,
    alternateTextColor: white,
    canvasColor: white,
    borderColor: colors.richBlack20,
    disabledColor: fade(colors.richBlack80, 0.3),
    pickerHeaderColor: colors.northwesternPurple,
    clockCircleColor: fade(colors.richBlack80, 0.07),
    shadowColor: fullBlack
  }
});

class App extends React.Component {
  render() {
    return (
      <Provider store={store}>
        <MuiThemeProvider muiTheme={muiTheme}>
          <div> {/* MuiThemeProvider requires stricly one child element */}
            <NavBar />
            <Serif /> {/* This component contains SearchContainer, which in turn contains Search */}
          </div>
        </MuiThemeProvider>
      </Provider>
    );
  }
}

ReactDOM.render(<App />, document.getElementById('app'));

最佳答案

您可以从另一个组件渲染您的搜索组件,我们将其称为SearchContainerSearchContainerconnect 装饰函数来自 react-redux它的唯一作用是 dispatch 行动去学校。在获取学校之前,SearchContainer 不会呈现 搜索 组件。

这里是代码的示例。这里我假设你不使用react-redux .

首先,reducers.js 中的初始状态存在一个小问题。应该是:

const initialState = {
  isFetching: false,
  lastUpdated: 0,
  schools: []
};

function schools(state = initialState, action) {
  switch (action.type) {
    case 'LOAD_SCHOOLS':
      return {
        ...state,
        isFetching: true
      };
    case 'RECEIVE_SCHOOLS':
      return {
        ...state,
        isFetching: false,
        schools: action.schools,
        lastUpdated: receivedAt
      }
    default:
      return state;
  }
}

SearchContainer.js

// ./containers/SearchContainer.js
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { loadSchools } from '../actions/actions'
import Search from '../components/Search';

class SearchContainer extends Component { 
  componentDidMount() {
    this.props.loadSchools(this.props.termId);
  },
  render() {
    const { 
      schools, 
      isFetching
    } = this.props;
    if (isFetching) {
      return null;
    }
    return <Search schools={schools} />;
  }
}

const mapStateToProps = (state) => ({
  isFetching: state.isFetching,
  schools: state.schools
});

const mapActionsToProps = (dispatch) => ({
  loadSchools: (termId) => dispatch(loadSchools(termId)),
});

export default connect(mapStateToProps, mapActionsToProps)(SearchContainer);

这样,在第一次渲染时,您的搜索组件不会被渲染。仅在学校加载后才会渲染。

关于javascript - React-Redux:如何使用异步调用中的数据填充组件的加载属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40627305/

相关文章:

javascript - 如何在 javascript 中隐藏弹出窗口的导航栏?

javascript - Carbone JS 与 React JS 的结合使用

reactjs - 当显示 'no results found' 时,如何以编程方式隐藏下拉菜单?

ios - 在 Swift 中使用 dispatchGroup 处理一系列异步函数时出错

javascript - 无法更改三个容器中的 SVG 矩形属性

javascript - Rails 表单通过 ajax post 提交,不调用成功或错误回调函数

javascript - 为什么 console.log 没有显示任何内容?

reactjs - React 测试库 - userEvent 上传到输入 : "cannot find toLowerCase"

angularjs - Angular UI Bootstrap Typeahead - 未显示异步结果

javascript - 显式等待 isPresent 和 isDisplayed 导致未找到元素失败