使用异步操作解析来反应redux并初始化props

时间:2016-04-15 07:27:46

标签: javascript reactjs redux

我正在学习redux并做出反应,而且我在道具初始化的良好实践方面遇到了一些问题。

事实上,我的路线如下:

/pokemons/:name

以下是相关部分:

import React from 'react';
import {connect} from 'react-redux';
import {showDetail} from './../../redux/modules/pokemons';

export class PokeDetail extends React.Component{

  render(){
    return(
      <div>
        {this.currentPokemon.name}
      </div>
    )
  }

}


const mapStateToProps = state => ({
  currentPokemon:state.pokemons.currentPokemon
});

export default connect((mapStateToProps),{
  showDetail
})(PokeDetail);

事实是我完全不知道 when / where 来发送我的操作以更改我的应用状态。事实上,我什么时候应该发送我的“showDetail('myPokemonName')”,以便currentPokemon状态会改变,我的应用程序可以工作?

如果可能,我需要一些好的做法

感谢您的帮助

编辑:

My PokeView :

import React from 'react';
import {connect} from 'react-redux';
import {loadRemoteAction} from './../../redux/modules/pokemons';
import {Link} from 'react-router';


export class PokeView extends React.Component {
  render(){
    let i = 0;
      return (
        <div>
        <h4>Super page</h4>
        <button onClick={this.props.loadRemoteAction}>Start</button>
        <ul>
        {
          this.props.pokemons.map(item => {
            i++;
            return <li key={i}><Link to={`/pokemons/${item.name}`}>{item.name}</Link></li>
          })
        }
        </ul>


        </div>
      );
  }
}

const mapStateToProps = state => ({
  pokemons : state.pokemons.pokemons
});


export default connect((mapStateToProps), {
  loadRemoteAction
})(PokeView);

我的行动/减速机:

import immutable from 'immutable';

/**
 * Action part
 */
export const LOAD_REMOTE = 'LOAD_REMOTE';
export const SHOW_DETAIL = 'SHOW_DETAIL';

export function loadRemoteAction() {
  return dispatch => {
    fetch('http://pokeapi.co/api/v2/pokemon/')
    .then(res => res.json())
    .then(res => dispatch({
      type:LOAD_REMOTE,
      payload:res.results
    }));
  };
}

export function showDetail(name){
  return {
    type:SHOW_DETAIL,
    payload:name
  }
}

/**
 * Reducer part
 */


const ACTION_HANDLER = {
  [LOAD_REMOTE] : (state, action) => {
    if(action.payload) return Object.assign({},state,{pokemons:state.pokemons.concat(action.payload)});
    return state;
  },
  [SHOW_DETAIL] : (state, action) =>{
    let  currentPokemon;
    for(const pkm of state.pokemons){
      if(pkm.name === action.payload) currentPokemon = pkm;
    }
    if(action.payload) return Object.assign({},state,{currentPokemon:currentPokemon});
    return state
  }
}


const initialState = {pokemons:immutable.fromJS([]), currentPokemon:immutable.fromJS({name:''})};
export default function pokemonReducer (state = initialState, action) {
  const handler = ACTION_HANDLER[action.type]
  return handler ? handler(state, action) : state
}

3 个答案:

答案 0 :(得分:3)

一般来说,行动就是世界上发生了某些事情 - 这通常是用户所做的事情,或者例如从后端到ajax调用的异步回答。在这些情况下,您希望发送操作(包含有关更改内容的信息),以便相应地更新状态树。 在您的情况下,如果您在屏幕上的其他位置显示Pokemons列表,并且用户点击其中一个,那么该点击会将点击的Pokemon保存到状态树,而您的PokeDetail组件将会然后获取此信息并显示所选口袋妖怪的详细信息。

在您的情况下,PokeView渲染功能可能如下所示:

export class PokeView extends React.Component {
  render(){
    return (
      <div>
        <h4>Super page</h4>
        <button onClick={this.props.loadRemoteAction}>Start</button>
        <ul>
        {
          this.props.pokemons.map((item, i) => <li key={i}><button onClick={this.props.dispatch(showDetail(item.name))}>{item.name}</button></li> )
        }
        </ul>
      </div>
    );
  }
}

并且PokeDetail类可能如下所示:

export class PokeDetail extends React.Component{
  render(){
    return <div>{this.props.currentPokemon.name}</div>;
  }
}

另一个问题是,信息最初如何进入我的应用程序?如果数据是静态的,您可以将其添加到初始状态树(通常将其作为默认参数传递给reducer函数),或者您可以通过Ajax调用从后端查询数据。后者可以在组件的componentDidMount生命周期方法中完成。 (为此,您需要redux-thunk才能使操作与回调和后端的异步应答一起工作。)

答案 1 :(得分:0)

您应该在componentWillMount函数中调用 showDetail 操作。

import React from 'react';
import {connect} from 'react-redux';
import {showDetail} from './../../redux/modules/pokemons';

export class PokeDetail extends React.Component{
  componentWillMount() {
    // If you are using react-router, route params will be in `params` property object.
    const pokemonId = this.props.params.id;
    this.props.showDetail(pokemonId);
  }

  componentWillReceiveProps(nextProps) {
    // Also you may want to update your component when url was changed.
    if (nextProps.params.id !== this.props.params.id) {
      this.props.showDetail(nextProps.params.id);
    }
  }

  render(){
    return(
      <div>
        {this.currentPokemon.name}
      </div>
    )
  }

}


const mapStateToProps = state => ({
  currentPokemon:state.pokemons.currentPokemon
});

export default connect((mapStateToProps),{
  showDetail
})(PokeDetail);

当您的组件正在挂载(或更新)时,您正在使用pokemon id调用您的操作。接下来,您的商店将会更新,您将在PokeDetail组件中收到所需的道具。

对于异步操作,您可能需要redux-thunk包。

答案 2 :(得分:-1)

您可以使用redux-async-connect包。您可以找到此包here的示例用法。