Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Same action for different state parts #1628

Closed
blvdmitry opened this issue Apr 17, 2016 · 7 comments
Closed

Same action for different state parts #1628

blvdmitry opened this issue Apr 17, 2016 · 7 comments
Labels

Comments

@blvdmitry
Copy link

Hey! (Warn: Rather new to Redux)

I have several forms on the same page that have inputs with suggests. So I thought I could possibly write abstract action creators for working with suggests:

import fetch from 'isomorphic-fetch';

export const FETCH_SUGGEST_DATA = 'FETCH_SUGGEST_DATA';
export const SET_SUGGEST_DATA = 'SET_SUGGEST_DATA';

export const fetchSuggestData = (url) => {
    return function (dispatch) {
        return fetch(url)
            .then(response => response.json())
            .then(json => dispatch(setSuggestData(json)))
    }
};

export const setSuggestData = (json) => {
    return {
        type: SET_SUGGEST_DATA,
        items: json.items
    }
};

and pass suggest reducer to different parts of the app reducer:

import { combineReducers } from 'redux';

import { suggest } from './form/suggest';

const app = combineReducers({
    mainForm: combineReducers({
        to: combineReducers({
            suggest: suggest
        })
    }),
        secondaryForm: combineReducers({
        from: combineReducers({
            suggest: suggest
        })
    }),
});

export default app;

If I dispatch a suggest action after onChange of any input triggers, I obviously get both suggests shown.
Is there any practice of specifying a part of the state for an action still keeping it abstract? Or maybe I should restructure the state somehow?

I've read this issue: #897 and those form examples were kinda close to the thing I'm trying to make. Still there is always a parent in these examples that must contain all of the inputs.

@markerikson
Copy link
Contributor

Speaking very generically, the couple main ways to handle this would be either wrapping your reducers to add some sort of additional distinguisher to the action constants, or adding an additional field to the actions that could be used.

I actually just posted a comment about this sort of thing on another issue a few days ago, linking to several related discussions and libraries. See #1602 (comment).

@blvdmitry
Copy link
Author

Thanks for the response, though it seems like I still need to restructure the state, as action also get data for suggest and saving it to ui state is like a huge hack that I will stuck on later :(

@blvdmitry
Copy link
Author

blvdmitry commented Apr 18, 2016

Upd: Currently stopped at implementation with passing context.

actions/suggest/suggest.js:

import fetch from "isomorphic-fetch";

export const SET_SUGGEST_DATA = "SET_SUGGEST_DATA";

export const fetchSuggestData = (context, url) => {
    return function (dispatch) {
        return fetch(url)
            .then(response => response.json())
            .then(json => dispatch(setSuggestData(context, json)))
    }
};

export const setSuggestData = (context, json) => {
    return {
        type: SET_SUGGEST_DATA,
        context,
        items: json.items
    }
};

reducers/index.js:

import { combineReducers } from 'redux';

import { suggest } from './suggest/suggest';

const app = combineReducers({
    mainForm: combineReducers({
        to: combineReducers({
            suggest: suggest.bind(null, 'mainForm.to')
        }),
        from: combineReducers({
            suggest: suggest.bind(null, 'mainForm.from')
        })
    })
});

export default app;

reducers/suggest/suggest.js:

import { SET_SUGGEST_DATA } from '../../actions/suggest/suggest';

let suggest = ( context, state = {}, action ) => {
    if (action.context !== context) return state;

    switch (action.type) {
        case SET_SUGGEST_DATA:
            let items = action.items;

            return {
                items: items,
                active: items.length
            };

        default:
            return state;
    }
};

export { suggest };

Probably there already is some similar way of getting the same result

@jcano
Copy link

jcano commented Apr 30, 2016

I think this is a really nice solution to the problem, without going into more advanced solutions like providers or adopting an Elm architecture.

I'll be trying it out and see where I can get. Have you found any issues with it so far?

@gaearon
Copy link
Contributor

gaearon commented May 1, 2016

Yeah, this is a good way to do it. We should add this to FAQ.

@gaearon gaearon added docs and removed question labels May 1, 2016
@blvdmitry
Copy link
Author

@jcano it seems to be a rather simple solution so I suppose that'll work nice. Wrote just a piece of a project using it and everything seems to be fine. Maybe automating it using some custom reducers combiner would be even better.

This was referenced May 30, 2016
@timdorr
Copy link
Member

timdorr commented Sep 27, 2016

Let's roll up some discussion into #1785 so this can be acted on. Hopefully soon! 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants