在异步调用中访问查询参数(react redux)

Access query parameters in async call (react redux)

我的 react redux (4.4.5) 项目使用 react-router-redux(4.0.5) 和 redux-async-connect (0.1.13)。在加载我的容器组件之前,我想从我的 API 中异步加载数据。 url 包含一个名为 "category" 的查询参数,用于获取消息。 IE。 user/cornel/messages?category=react-redux

链接到我的 location/path 的参数在 state.routing.locationBeforeTransitions 中,但在异步调用中这些参数不是最新的。我可以从传递给异步函数的 params 参数中获取路径参数,但这不包含查询参数。

@statics({
  reduxAsyncConnect(params, store) {
    const { dispatch } = store;
    return Promise.all([
      dispatch(loadMessages(category)) <-- need the query parameter "category" here
    ]);
  }
})
@connect(state => ({
  messages: state.user.messages
}))
export default class HomeContainer extends Component {
  static propTypes = {
    dispatch: PropTypes.func
    messages: PropTypes.array.isRequired
  };

  render() {
    const { messages } = this.props;

    return (
      ...
    }
  }
}

有人知道我应该如何访问查询参数以便它在客户端和服务器端都有效吗? 提前致谢!

如果你使用的是 react-redux-router,你应该能够从 redux state 中进行搜索,如下所示。

@statics({
  reduxAsyncConnect(params, store) {
    const { dispatch } = store;
    return Promise.all([
      dispatch(loadMessages(category)) <-- need the query parameter "category" here
    /* you might get 
      store.getState().
          routing.locationBeforeTransitions.search 
      from here too */
    ]);
  }
})
@connect(state => ({
  messages: state.user.messages,
  /* get search from redux state */
  search : state.routing.locationBeforeTransitions.search
}))
export default class HomeContainer extends Component {
  static propTypes = {
    dispatch: PropTypes.func
    messages: PropTypes.array.isRequired
  };

  render() {
    const { messages } = this.props;

    return (
      ...
    }
  }
}

如果您无法使用,请告诉我。

编辑

这是一段不使用 reduxAsyncConnect 并完成你想做的事情的代码。

// CONSTANTS
const
  GET_SOMETHING_FROM_SERVER = 'GET_SOMETHING_FROM_SERVER',
  GET_SOMETHING_FROM_SERVER_SUCCESS = 'GET_SOMETHING_FROM_SERVER_SUCCESS',
  GET_SOMETHING_FROM_SERVER_FAIL = 'GET_SOMETHING_FROM_SERVER_FAIL';

// REDUCER
const initialState = {
  something : [],
  loadingGetSomething: false,
  loadedGetSomething:false,
  loadGetSomethingError:false
};

export default function reducer(state = initialState, action) {

  switch(action.type) {

    case GET_SOMETHING_FROM_SERVER:
      return Object.assign({}, state, {
        loadingGetSomething: true,
        loadedGetSomething:false,
        loadGetSomethingError:false
        something : [] // optional if you want to get rid of old data
      });
    case GET_SOMETHING_FROM_SERVER_SUCCESS:
      return Object.assign({}, state, {
        loadingGetSomething: false,
        loadedGetSomething:true,
        something : action.data
      });
    case GET_SOMETHING_FROM_SERVER_FAIL:
      return Object.assign({}, state, {
        loadingGetSomething: false,
        loadGetSomethingError: action.data
      });
    default:
      return state;
  }

};

// ACTIONS

/* ----------------- GET SOMETHING ACTIONS START ----------------- */
import Fetcher from 'isomorphic-fetch'; // superagent , axios libs are okay also 

export function getSomething() {
  return {
    type : GET_SOMETHING_FROM_SERVER
  }
};
export function getSomethingSuccess(data) {
  return {
    type : GET_SOMETHING_FROM_SERVER_SUCCESS,
    data
  }
};
export function getSomethingFail(data) {
  return {
    type : GET_SOMETHING_FROM_SERVER_FAIL,
    data
  }
};
export function getSomethingAsync(paramsToBeSentFromComponents){
  return function(dispatch) {
    const fetcher = new Fetcher();

    dispatch(getSomething()); // so we can show a loading gif 

    fetcher
      .fetch('/api/views', {
        method : 'POST',
        data : {
          // use paramsToBeSentFromClient
        }
      })
      .then((response) => {
        dispatch( getSomethingSuccess(response.data));
      })
      .catch((error) => {
        return dispatch(getSomethingFail({
          error : error        
        }))
      });
  }
}
/* ----------------- GET SOMETHING ACTIONS END ----------------- */


// COMPONENT

import React, {Component}       from 'react';
import { connect }              from 'react-redux';
import { bindActionCreators }   from 'redux';
import * as somethignActions    from './redux/something';

@connect((state) => ({
  pathname : state.routing.locationBeforeTransitions.pathname,
  something : state.something
}))

export default class SettingsMain extends Component{

  constructor(props){
    super(props);
    this.somethingActions = bindActionCreators(somethingActions, this.props.dispatch);
  }

  componentDidMount(){
    // you are free to call your async function whenever 
    this.settingActions.getSomething({ this.props.pathname...... })
  }

  render(){
    return ( /* your components */ )
  }
}