簡體   English   中英

React-Redux:如何使用異步調用中的數據填充加載時的組件的prop?

[英]React-Redux: How do I populate a component's prop on load with data from an async call?

我有這個自動完成組件,它需要一個術語數組作為dataSource屬性。 我要輸入的數據駐留在公共API中,我已經按照此處的教程操作以獲取以下代碼。 但是本教程(以及其他許多教程)介紹了如何將這些動作綁定到事件,而我想用頁面加載數據填充此道具。 我將如何去做?

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'));

您可以從另一個組件渲染Search組件,我們稱其為SearchContainer SearchContainerreact-reduxconnect函數裝飾,該函數僅具有分派動作以獲取學校的作用。 在獲取學校之前, 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);

這樣,在第一次渲染時,不會渲染您的Search組件。 僅在加載學校之后才渲染它。

您可以從componentDidMount生命周期方法(可能在您的Serif組件中,但我看不到該代碼)中調度LOAD_SCHOOLS操作。

從文檔:

掛載組件后立即調用componentDidMount() 需要DOM節點的初始化應在此處進行。 如果您需要從遠程端點加載數據,那么這是實例化網絡請求的好地方 在此方法中設置狀態將觸發重新渲染。

https://facebook.github.io/react/docs/react-component.html#componentdidmount

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM