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

Show how to reuse actions within actions in docs? #75

Open
jaredpalmer opened this issue Feb 13, 2018 · 4 comments
Open

Show how to reuse actions within actions in docs? #75

jaredpalmer opened this issue Feb 13, 2018 · 4 comments
Labels

Comments

@jaredpalmer
Copy link
Contributor

jaredpalmer commented Feb 13, 2018

This works... maybe worth adding to the readme.

// If actions is a function, it gets passed the store:
let actions = store => ({
  // Actions can just return a state update:
  increment(state) {
    return { count: state.count + 1 };
  },
   // The above example as an Arrow Function:
  increment2: ({ count }) => ({ count: count + 1 }),

  // Async actions are actions that call store.setState():
  incrementAsync(state) {
    store.setState(this.increment(state));
    setTimeout(() => {
      store.setState({ count: store.getState().count + 1 });
    }, 1000);
  },
});
@jaredpalmer jaredpalmer changed the title Add thunk-like "action" Feb 13, 2018
@jaredpalmer jaredpalmer changed the title Add thunk-like "action" to docs? Feb 13, 2018
@davidchase
Copy link

davidchase commented Feb 28, 2018

Hmm i tried that, but my this is bound to onClick if we refer to the example in the README.

edit
and binding each function to actions object for correct context seems a bit tedious, it would be nice if it was passed in as parameter al la FormidableLabs/freactal where they are called effects

@ehaynes99
Copy link

ehaynes99 commented Apr 3, 2018

@jaredpalmer Your async action increments the count twice, FYI.

@davidchase Binding of this is a flaw in the javascript language, not unistore. You can just initialize all the actions as pure functions and return and object that references them so you're not using this for anything. E.g.

export default (store) => {
  const increment = (state) => {
    return {
      count: state.count + 1,
    }
  }

  const incrementAsync = (state) => {
    setTimeout(() => {
      store.setState(increment(state))
    }, 1000)
  }

  return {
    increment,
    incrementAsync,
  }
}
@developit
Copy link
Owner

developit commented Apr 27, 2018

Might be worth changing the readme to more explicitly spell out the outer function and calling contexts:

// If actions is a function, it gets passed the store:
function createActions(store) {
  const actions = {
    // Actions can just return a state update:
    increment(state) {
      return { count: state.count + 1 };
    },
     // The above example as an Arrow Function:
    increment2: ({ count }) => ({ count: count + 1 }),

    // Async actions are actions that call store.setState():
    incrementAsync(state) {
      store.setState(actions.increment(state));
      setTimeout(() => {
        store.setState({ count: store.getState().count + 1 });
      }, 1000);
    }
  };

  return actions;
}

Otherwise I'd recommend something like what @ehaynes99 suggested - avoid context entirely.

@damianobarbati
Copy link

I'm trying to avoid the wrapping/context to have my actions.js be a collection of pure functions but it makes hard to have a "thunk" like functionality.
How can I achieve something like the following without having to import the store into actions.js and without wrapping actions into a context/function?

const setName = (state, name) => {
  state.name = name;
  validateName(state, name); //async but nobody will get this state update?
  return state:
};

const validateName = async (state, name) => {
   const isValid = await ... // axios stuff...
   state.nameIsValid = isValid;
   return state; // wait! this state is STALE, because I'm returning an old version of state
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
5 participants