Ron
Ron

Reputation: 6735

In redux+react web app, how to know one async action is finally dispatched to state

Rudx-thunk did a great job to dispatch async actions, it will eventually modify the state fetched in async action. But how do I know the moment when it finally modify the redux state fetched?

In my case, I want to read config from the server, because there are components need these config so I have to render the whole app after the config is fetched. But so far I cannot work out by using redux-thunk or any other redux async middlewares.

Update #1 show some code to express myself better.

// reducer
(state, action) => Object.assign({}, state, {config: action.config});

// action creator
const fetchConfig = () => (dispatch) => {
    fetch('http://server.com/...')
    .then(config=>dispatch({type: 'LOAD_CONFIG', config}))
}

// connect reducer to state
createStore({config: configReducer})

// render
import { render } from 'react-dom';
render (<App><News /></App>)

// some component consume state.config
@connect(state=>{config: state.config})
const News = props=>(
    <div>
        {(props.config === '...')? <div>...</div> : <div>...</div>}
    </div>
)

The above looks good, however due to the action may take time and update the states after the component first render, so the component may display unexpected results. What I really want to do is (I just write down the render part, others should be the same):

// render
loadConfigFinished
.then(()=> render((<App><News /></App>)))

Or

// render
on('loadConfigFinished', ()=> render((<App><News /></App>)));

Probably, I should do the 2nd way, just afraid it is not redux-y.

Anyway, the above is just a example showing sometimes we do need to be notified when some action finally dispatch to the redux state.

Upvotes: 0

Views: 370

Answers (3)

pfkurtz
pfkurtz

Reputation: 514

Looking at your code, I gather your question is simply: When do I render a component that depends on data from the server, while waiting for that data, without passing undefined into my component?

I would have a container component that connects to the config state, and conditionally renders the component that needs it, or a loading template:

const Container = props => {
  if (props.config) {
    return <ConfiguredComponent config={props.config} />
  } else {
    return <Loading />
  }
}

Upvotes: 2

flup
flup

Reputation: 27104

When your reducers process the readConfigSuccess action, they update the redux state.

The application gets re-rendered with updated props for all state changes so there's nothing special about this particular action.

Except that usually only a small part of the state changes and the rerender looks a lot like the previous render and here I'd expect that a relatively large part of the state gets changed by the reducers for this particular action and a rerender will render a much changed application.

That's not for you to worry about though, it should Just Work.

Or do you mean something else, would you like to do more async work as a result of retrieving the config?

Upvotes: 0

ffxsam
ffxsam

Reputation: 27713

export function readConfig() {
  return (dispatch) => {
    dispatch(readingConfig());

    someAsyncFunction((error, result) => {
      if (!error) {
        dispatch(readConfigSuccess(result));
      } else {
        dispatch(readConfigFail(error));
      }
    });
  }
}

And of course, readConfigSuccess, readConfigFail, and readingConfig are action creator functions that return action objects, e.g.:

export const READING_CONFIG = 'READING_CONFIG';
export function readingConfig() {
  return {
    type: READING_CONFIG,
  }
}

Upvotes: 0

Related Questions