0

My react redux (4.4.5) project uses react-router-redux(4.0.5) and redux-async-connect (0.1.13). Before I load my container component, I want to asynchronously load data from my API. The url contains a query parameter named "category" which is used to fetch the messages. ie. user/cornel/messages?category=react-redux

The parameters linked to my location/path are in state.routing.locationBeforeTransitions, but these are not up to date when in the async call. I can get the path parameters from the params parameter that is passed to the async function, but this does not contain the query parameters.

@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 (
      ...
    }
  }
}

Anyone has any idea how I should access the query parameter so it works both client and server side? Thanks in advance!

1 Answer 1

1

You should be able to get search from redux state as the following if you are using react-redux-router.

@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 (
      ...
    }
  }
}

Let me know if it is not available for you.

EDIT

Here is a piece of code that doesn't use reduxAsyncConnect and accomplishing what you want to do.

// 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 */ )
  }
}
Sign up to request clarification or add additional context in comments.

7 Comments

store.getState(). routing.locationBeforeTransitions.search is an empty string. I think its because it is not updated to the latest url change. It is available though on the actual props while rendering the component.
When do you need to fire this function ? After your component mounted on page in a different route or before that ? I am also not familiar with reduxAsyncConnect. You could easily call your async function from component and pass the gotten props....search on componentWillMount or something.
reduxAsyncConnect fires the function before the component is mounted. It used to work with react-router-redux v3.
I see. I took a look at reduxAsyncConnect and it seems to make its first request in componentDidMount(). Which should mean you should be able to get newProps. You might try to put debugger in your code to see if it is stale redux state your reduxAsyncConnect gets.
store.getState(). routing.locationBeforeTransitions is outdated in the reduxAsyncConnect. The still has the old values (pathname, query), while the props in the render have the correct values.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.