Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make api calls from dumb components with Redux

Tags:

redux

I want to implement dropdown with react and redux. Dropdown will be a part of other component, so, it it really "Dumb" component. But dropdown should call to api to fetch items, apply custom filters and etc. Api calls should be authenticated, tokens stored it global state. Should I pass tokens to component props? Or there is a better way to do this?

like image 332
Artur Eshenbrener Avatar asked Oct 30 '15 06:10

Artur Eshenbrener


2 Answers

A dumb component, by definition, should be dumb: it means that it should take everything it needs "from the top", i.e. via the props.

Only a "Smart" ("connected" to Redux) Component, up the hierarchy, would deal with fetching the data using a new (async) Action, which would then modify the state when the API call returns, which would re-render your Dumb Component with its new props.

So in Redux:

  • Your Dumb component takes two props: one with the values coming from your API (which actually are part of your "state"), the other one a function that is called when your dropdown selected item changes. <MyDumbComponent data={this.props.data} onChange={this.onChange.bind(this)} />
  • Then a "Smart" component up the hierarchy will listen to that onChange function, and dispatch an Action (FETCH_DATA)
  • The (async) Action will call the API, and when receiving the data, call another Action (FETCH_DATA_SUCCESS) with the data
  • Then Redux, with a reducer, would update its state from the Action payload
  • Which will re-render your Component with its new props (new data), coming from the current state.

You might want to read this: http://redux.js.org/docs/basics/UsageWithReact.html

And regarding async actions: http://redux.js.org/docs/advanced/AsyncActions.html

like image 111
Antoine Jaussoin Avatar answered Jan 01 '23 19:01

Antoine Jaussoin


Dumb component doesn't mean it can do anything like fetch updates, it means it's 'dumb' to the concept of redux, and knows nothing about your store or what library you're using. The benefit is that you can change your flux implementation and you only have the small bit of work to update the smart components.

For the type of scenario you're describing, you would give your <Menu> a function via props that would run when <Menu> wants to update the data. <Menu> knows nothing about Redux - it's just executing a function - but it's still able to fetch new data. Depending on the complexities, you could pass through the raw action creator (bound to dispatchAction) and have it run that.

import * as dataActions from './actions';
// We have dataActions.fetchItems() which is the action creater to get new items.

// Attach items, and the action creator (bound to dispatch) to props
@connect((store) => {
    return {items: store.data.items}
}, dataActions)
class ItemsPage extends Component {
    static propTypes = {
        items: PropTypes.object, // the items from the store, from @connect
        fetchItems: PropTypes.func // action dispatcher, from @connect
    }

    render() {
        return (<Menu onChange={this.props.fetchItems} /> )
    }
}

// Our 'dumb' component that doesnt know anything about Redux,
// but is still able to update data (via its smart parent)
class Menu extends Component {
    static propTypes = {
        onChange: PropTypes.func // same as fetchItems
    }

    render() {
        return (<button onClick={this.props.onChange}>Update items</button>);
    }
}
like image 43
Josh Hunt Avatar answered Jan 01 '23 19:01

Josh Hunt