Redux Recipe List












1














I made a simple React + Redux app which allows you to add and remove recipes to a list.



Here are the user stories the app fulfills:




User Story: I can create recipes that have names and ingredients.



User Story: I can see an index view where the names of all the recipes are visible.



User Story: I can click into any of those recipes to view it.



User Story: I can delete these recipes.




User Story: All new recipes I add are saved in my browser's local storage. If I refresh the page, these recipes will still be there.



Code:



import React from 'react'
import ReactDOM from 'react-dom'
import { connect } from 'react-redux'
import { createStore } from 'redux'

const ADD_RECIPE = 'ADD_RECIPE'
const SHOW_RECIPE = 'SHOW_RECIPE'
const EDIT_RECIPE = 'EDIT_RECIPE'
const UPDATE_ACTIVE_NAME = 'UPDATE_ACTIVE_NAME'
const UPDATE_ACTIVE_INGREDIENTS = 'UPDATE_ACTIVE_INGREDIENTS'
const TOGGLE_ACTIVE_ID = 'TOGGLE_ACTIVE_ID'
const DELETE_RECIPE = 'DELETE_RECIPE'

const initialState = {
activeName: '',
activeIngredients: '',
activeId: '',
recipes: [
{
id: 1,
name: 'Pizza',
ingredients: 'Dough, tomato, cheese, salt, pepper, olives, mushrooms, ham.'
},
{
id: 2,
name: 'Sherpherd's Pie',
ingredients: 'Potato, lamb'
},
{
id: 3,
name: 'Huel Shake',
ingredients: 'Milk, huel'
}
]
}

// action creators
const saveStoreRecipesToLocalStorage = (state) => {
localStorage.setItem('state', JSON.stringify(
{...state, activeId: ""}
));
}

const getStoreRecipesFromLocalStorage = () => {
const state = JSON.parse(localStorage.getItem('state'))
return state.recipes.length && state
}

const addRecipe = (id, name, ingredients) => {
return {
type: ADD_RECIPE,
payload: {
id,
name,
ingredients
}
}
}

const updateActiveName = payload => {
return {
type: UPDATE_ACTIVE_NAME,
payload
}
}

const updateActiveIngredients = payload => {
return {
type: UPDATE_ACTIVE_INGREDIENTS,
payload
}
}

const toggleActiveId = id => {
return {
type: TOGGLE_ACTIVE_ID,
payload: id
}
}

const deleteRecipe = id => {
return {
type: DELETE_RECIPE,
payload: id
}
}

// reducer
function recipes (state = getStoreRecipesFromLocalStorage() || initialState, action) {
console.warn('action:', action)
switch (action.type) {
case TOGGLE_ACTIVE_ID:
return {...state, activeId: action.payload}
case UPDATE_ACTIVE_NAME:
return {...state, activeName: action.payload}
case UPDATE_ACTIVE_INGREDIENTS:
return {...state, activeIngredients: action.payload}
case ADD_RECIPE:
return {...state, recipes: [...state.recipes, action.payload]}
case DELETE_RECIPE:
return {...state, recipes: state.recipes.filter(recipe => recipe.id !== action.payload)}
case EDIT_RECIPE:
return
default:
return state
}
}

const Recipes = (props) => {
getStoreRecipesFromLocalStorage()
const {addRecipe, updateActiveIngredients, updateActiveName, toggleActiveId, deleteRecipe, state} = props
const id = new Date().getTime() / 1000
return (
<div style={{width: 320}}>
<form onSubmit={e => {
e.preventDefault()
addRecipe(id, state.activeName, state.activeIngredients)
}}>
<input
type="text"
placeholder="Name"
value={state.activeName}
onChange={(e) => updateActiveName(e.target.value)}
/>
<input
placeholder="Ingredients"
value={state.activeIngredients}
onChange={e => updateActiveIngredients(e.target.value)}
/>
<button type="submit">Add Recipe</button>
</form>
{state.recipes.map(item => <ul key={item.name}>
<div style={{display: 'flex', justifyContent: 'space-between'}}>
<li onClick={() => toggleActiveId(item.id)}>
<div>{item.name}</div>
{state.activeId === item.id && <div>{item.ingredients}</div>}
</li>
<div style={{color: 'red'}} onClick={() => deleteRecipe(item.id)}>&times;</div>
</div>
</ul>)}

</div>
)
}

const mapStateToProps = (state) => {
return {
state
}
}

const mapDispatchToProps = (dispatch, ownProps) => {
return {
addRecipe: (id, name, ingredients) => {
if (name && ingredients) {
dispatch(addRecipe(id, name, ingredients))
dispatch(updateActiveName(''))
dispatch(updateActiveIngredients(''))
saveStoreRecipesToLocalStorage(ownProps.store.getState())
}
},
updateActiveName: name => dispatch(updateActiveName(name)),
updateActiveIngredients: ingredients => dispatch(updateActiveIngredients(ingredients)),
toggleActiveId: id => dispatch(toggleActiveId(id)),
deleteRecipe: id => {
dispatch(deleteRecipe(id))
saveStoreRecipesToLocalStorage(ownProps.store.getState())
}
}
}

const App = connect(
mapStateToProps,
mapDispatchToProps
)(Recipes)

const store = createStore(recipes, window.__REDUX_DEVTOOLS_EXTENSION__())
const render = () => ReactDOM.render(<App store={store}/>, document.getElementById('root'))
store.subscribe(render)
render()


I would like to structure the app better by splitting this file into separate files but for the sake of this question I have kept it in one file.



Demo (adapted for codepen without localStorage features): https://codepen.io/alanbuchanan/pen/LQWKBZ



Making this small app brought about some questions I have about Redux:




  1. I have an updateActiveName and updateActiveIngredients function because there are only these two fields that get added by the form. Would it be better instead to use an updateActiveObject and run this when either field changes? I see this as a benefit for when other fields get added, but less efficient because I will be running an onChange function for several fields that aren't changing.


  2. The naming of my action creators, reducers, and functions inside mapDispatchToProps are usually the same. For example UPDATE_ACTIVE_INGREDIENTS, updateActiveIngredients action creator and updateActiveIngredients function. Is there a better approach to this?


  3. In the addRecipe function inside mapDispatchToProps, I am validating the name and ingredients values. Should this go inside this function, or somewhere else?


  4. In the addRecipe function inside mapDispatchToProps, I am dispatching many actions. Is this correct practise?



Any other feedback for improving my Redux is most welcome.










share|improve this question





























    1














    I made a simple React + Redux app which allows you to add and remove recipes to a list.



    Here are the user stories the app fulfills:




    User Story: I can create recipes that have names and ingredients.



    User Story: I can see an index view where the names of all the recipes are visible.



    User Story: I can click into any of those recipes to view it.



    User Story: I can delete these recipes.




    User Story: All new recipes I add are saved in my browser's local storage. If I refresh the page, these recipes will still be there.



    Code:



    import React from 'react'
    import ReactDOM from 'react-dom'
    import { connect } from 'react-redux'
    import { createStore } from 'redux'

    const ADD_RECIPE = 'ADD_RECIPE'
    const SHOW_RECIPE = 'SHOW_RECIPE'
    const EDIT_RECIPE = 'EDIT_RECIPE'
    const UPDATE_ACTIVE_NAME = 'UPDATE_ACTIVE_NAME'
    const UPDATE_ACTIVE_INGREDIENTS = 'UPDATE_ACTIVE_INGREDIENTS'
    const TOGGLE_ACTIVE_ID = 'TOGGLE_ACTIVE_ID'
    const DELETE_RECIPE = 'DELETE_RECIPE'

    const initialState = {
    activeName: '',
    activeIngredients: '',
    activeId: '',
    recipes: [
    {
    id: 1,
    name: 'Pizza',
    ingredients: 'Dough, tomato, cheese, salt, pepper, olives, mushrooms, ham.'
    },
    {
    id: 2,
    name: 'Sherpherd's Pie',
    ingredients: 'Potato, lamb'
    },
    {
    id: 3,
    name: 'Huel Shake',
    ingredients: 'Milk, huel'
    }
    ]
    }

    // action creators
    const saveStoreRecipesToLocalStorage = (state) => {
    localStorage.setItem('state', JSON.stringify(
    {...state, activeId: ""}
    ));
    }

    const getStoreRecipesFromLocalStorage = () => {
    const state = JSON.parse(localStorage.getItem('state'))
    return state.recipes.length && state
    }

    const addRecipe = (id, name, ingredients) => {
    return {
    type: ADD_RECIPE,
    payload: {
    id,
    name,
    ingredients
    }
    }
    }

    const updateActiveName = payload => {
    return {
    type: UPDATE_ACTIVE_NAME,
    payload
    }
    }

    const updateActiveIngredients = payload => {
    return {
    type: UPDATE_ACTIVE_INGREDIENTS,
    payload
    }
    }

    const toggleActiveId = id => {
    return {
    type: TOGGLE_ACTIVE_ID,
    payload: id
    }
    }

    const deleteRecipe = id => {
    return {
    type: DELETE_RECIPE,
    payload: id
    }
    }

    // reducer
    function recipes (state = getStoreRecipesFromLocalStorage() || initialState, action) {
    console.warn('action:', action)
    switch (action.type) {
    case TOGGLE_ACTIVE_ID:
    return {...state, activeId: action.payload}
    case UPDATE_ACTIVE_NAME:
    return {...state, activeName: action.payload}
    case UPDATE_ACTIVE_INGREDIENTS:
    return {...state, activeIngredients: action.payload}
    case ADD_RECIPE:
    return {...state, recipes: [...state.recipes, action.payload]}
    case DELETE_RECIPE:
    return {...state, recipes: state.recipes.filter(recipe => recipe.id !== action.payload)}
    case EDIT_RECIPE:
    return
    default:
    return state
    }
    }

    const Recipes = (props) => {
    getStoreRecipesFromLocalStorage()
    const {addRecipe, updateActiveIngredients, updateActiveName, toggleActiveId, deleteRecipe, state} = props
    const id = new Date().getTime() / 1000
    return (
    <div style={{width: 320}}>
    <form onSubmit={e => {
    e.preventDefault()
    addRecipe(id, state.activeName, state.activeIngredients)
    }}>
    <input
    type="text"
    placeholder="Name"
    value={state.activeName}
    onChange={(e) => updateActiveName(e.target.value)}
    />
    <input
    placeholder="Ingredients"
    value={state.activeIngredients}
    onChange={e => updateActiveIngredients(e.target.value)}
    />
    <button type="submit">Add Recipe</button>
    </form>
    {state.recipes.map(item => <ul key={item.name}>
    <div style={{display: 'flex', justifyContent: 'space-between'}}>
    <li onClick={() => toggleActiveId(item.id)}>
    <div>{item.name}</div>
    {state.activeId === item.id && <div>{item.ingredients}</div>}
    </li>
    <div style={{color: 'red'}} onClick={() => deleteRecipe(item.id)}>&times;</div>
    </div>
    </ul>)}

    </div>
    )
    }

    const mapStateToProps = (state) => {
    return {
    state
    }
    }

    const mapDispatchToProps = (dispatch, ownProps) => {
    return {
    addRecipe: (id, name, ingredients) => {
    if (name && ingredients) {
    dispatch(addRecipe(id, name, ingredients))
    dispatch(updateActiveName(''))
    dispatch(updateActiveIngredients(''))
    saveStoreRecipesToLocalStorage(ownProps.store.getState())
    }
    },
    updateActiveName: name => dispatch(updateActiveName(name)),
    updateActiveIngredients: ingredients => dispatch(updateActiveIngredients(ingredients)),
    toggleActiveId: id => dispatch(toggleActiveId(id)),
    deleteRecipe: id => {
    dispatch(deleteRecipe(id))
    saveStoreRecipesToLocalStorage(ownProps.store.getState())
    }
    }
    }

    const App = connect(
    mapStateToProps,
    mapDispatchToProps
    )(Recipes)

    const store = createStore(recipes, window.__REDUX_DEVTOOLS_EXTENSION__())
    const render = () => ReactDOM.render(<App store={store}/>, document.getElementById('root'))
    store.subscribe(render)
    render()


    I would like to structure the app better by splitting this file into separate files but for the sake of this question I have kept it in one file.



    Demo (adapted for codepen without localStorage features): https://codepen.io/alanbuchanan/pen/LQWKBZ



    Making this small app brought about some questions I have about Redux:




    1. I have an updateActiveName and updateActiveIngredients function because there are only these two fields that get added by the form. Would it be better instead to use an updateActiveObject and run this when either field changes? I see this as a benefit for when other fields get added, but less efficient because I will be running an onChange function for several fields that aren't changing.


    2. The naming of my action creators, reducers, and functions inside mapDispatchToProps are usually the same. For example UPDATE_ACTIVE_INGREDIENTS, updateActiveIngredients action creator and updateActiveIngredients function. Is there a better approach to this?


    3. In the addRecipe function inside mapDispatchToProps, I am validating the name and ingredients values. Should this go inside this function, or somewhere else?


    4. In the addRecipe function inside mapDispatchToProps, I am dispatching many actions. Is this correct practise?



    Any other feedback for improving my Redux is most welcome.










    share|improve this question



























      1












      1








      1


      3





      I made a simple React + Redux app which allows you to add and remove recipes to a list.



      Here are the user stories the app fulfills:




      User Story: I can create recipes that have names and ingredients.



      User Story: I can see an index view where the names of all the recipes are visible.



      User Story: I can click into any of those recipes to view it.



      User Story: I can delete these recipes.




      User Story: All new recipes I add are saved in my browser's local storage. If I refresh the page, these recipes will still be there.



      Code:



      import React from 'react'
      import ReactDOM from 'react-dom'
      import { connect } from 'react-redux'
      import { createStore } from 'redux'

      const ADD_RECIPE = 'ADD_RECIPE'
      const SHOW_RECIPE = 'SHOW_RECIPE'
      const EDIT_RECIPE = 'EDIT_RECIPE'
      const UPDATE_ACTIVE_NAME = 'UPDATE_ACTIVE_NAME'
      const UPDATE_ACTIVE_INGREDIENTS = 'UPDATE_ACTIVE_INGREDIENTS'
      const TOGGLE_ACTIVE_ID = 'TOGGLE_ACTIVE_ID'
      const DELETE_RECIPE = 'DELETE_RECIPE'

      const initialState = {
      activeName: '',
      activeIngredients: '',
      activeId: '',
      recipes: [
      {
      id: 1,
      name: 'Pizza',
      ingredients: 'Dough, tomato, cheese, salt, pepper, olives, mushrooms, ham.'
      },
      {
      id: 2,
      name: 'Sherpherd's Pie',
      ingredients: 'Potato, lamb'
      },
      {
      id: 3,
      name: 'Huel Shake',
      ingredients: 'Milk, huel'
      }
      ]
      }

      // action creators
      const saveStoreRecipesToLocalStorage = (state) => {
      localStorage.setItem('state', JSON.stringify(
      {...state, activeId: ""}
      ));
      }

      const getStoreRecipesFromLocalStorage = () => {
      const state = JSON.parse(localStorage.getItem('state'))
      return state.recipes.length && state
      }

      const addRecipe = (id, name, ingredients) => {
      return {
      type: ADD_RECIPE,
      payload: {
      id,
      name,
      ingredients
      }
      }
      }

      const updateActiveName = payload => {
      return {
      type: UPDATE_ACTIVE_NAME,
      payload
      }
      }

      const updateActiveIngredients = payload => {
      return {
      type: UPDATE_ACTIVE_INGREDIENTS,
      payload
      }
      }

      const toggleActiveId = id => {
      return {
      type: TOGGLE_ACTIVE_ID,
      payload: id
      }
      }

      const deleteRecipe = id => {
      return {
      type: DELETE_RECIPE,
      payload: id
      }
      }

      // reducer
      function recipes (state = getStoreRecipesFromLocalStorage() || initialState, action) {
      console.warn('action:', action)
      switch (action.type) {
      case TOGGLE_ACTIVE_ID:
      return {...state, activeId: action.payload}
      case UPDATE_ACTIVE_NAME:
      return {...state, activeName: action.payload}
      case UPDATE_ACTIVE_INGREDIENTS:
      return {...state, activeIngredients: action.payload}
      case ADD_RECIPE:
      return {...state, recipes: [...state.recipes, action.payload]}
      case DELETE_RECIPE:
      return {...state, recipes: state.recipes.filter(recipe => recipe.id !== action.payload)}
      case EDIT_RECIPE:
      return
      default:
      return state
      }
      }

      const Recipes = (props) => {
      getStoreRecipesFromLocalStorage()
      const {addRecipe, updateActiveIngredients, updateActiveName, toggleActiveId, deleteRecipe, state} = props
      const id = new Date().getTime() / 1000
      return (
      <div style={{width: 320}}>
      <form onSubmit={e => {
      e.preventDefault()
      addRecipe(id, state.activeName, state.activeIngredients)
      }}>
      <input
      type="text"
      placeholder="Name"
      value={state.activeName}
      onChange={(e) => updateActiveName(e.target.value)}
      />
      <input
      placeholder="Ingredients"
      value={state.activeIngredients}
      onChange={e => updateActiveIngredients(e.target.value)}
      />
      <button type="submit">Add Recipe</button>
      </form>
      {state.recipes.map(item => <ul key={item.name}>
      <div style={{display: 'flex', justifyContent: 'space-between'}}>
      <li onClick={() => toggleActiveId(item.id)}>
      <div>{item.name}</div>
      {state.activeId === item.id && <div>{item.ingredients}</div>}
      </li>
      <div style={{color: 'red'}} onClick={() => deleteRecipe(item.id)}>&times;</div>
      </div>
      </ul>)}

      </div>
      )
      }

      const mapStateToProps = (state) => {
      return {
      state
      }
      }

      const mapDispatchToProps = (dispatch, ownProps) => {
      return {
      addRecipe: (id, name, ingredients) => {
      if (name && ingredients) {
      dispatch(addRecipe(id, name, ingredients))
      dispatch(updateActiveName(''))
      dispatch(updateActiveIngredients(''))
      saveStoreRecipesToLocalStorage(ownProps.store.getState())
      }
      },
      updateActiveName: name => dispatch(updateActiveName(name)),
      updateActiveIngredients: ingredients => dispatch(updateActiveIngredients(ingredients)),
      toggleActiveId: id => dispatch(toggleActiveId(id)),
      deleteRecipe: id => {
      dispatch(deleteRecipe(id))
      saveStoreRecipesToLocalStorage(ownProps.store.getState())
      }
      }
      }

      const App = connect(
      mapStateToProps,
      mapDispatchToProps
      )(Recipes)

      const store = createStore(recipes, window.__REDUX_DEVTOOLS_EXTENSION__())
      const render = () => ReactDOM.render(<App store={store}/>, document.getElementById('root'))
      store.subscribe(render)
      render()


      I would like to structure the app better by splitting this file into separate files but for the sake of this question I have kept it in one file.



      Demo (adapted for codepen without localStorage features): https://codepen.io/alanbuchanan/pen/LQWKBZ



      Making this small app brought about some questions I have about Redux:




      1. I have an updateActiveName and updateActiveIngredients function because there are only these two fields that get added by the form. Would it be better instead to use an updateActiveObject and run this when either field changes? I see this as a benefit for when other fields get added, but less efficient because I will be running an onChange function for several fields that aren't changing.


      2. The naming of my action creators, reducers, and functions inside mapDispatchToProps are usually the same. For example UPDATE_ACTIVE_INGREDIENTS, updateActiveIngredients action creator and updateActiveIngredients function. Is there a better approach to this?


      3. In the addRecipe function inside mapDispatchToProps, I am validating the name and ingredients values. Should this go inside this function, or somewhere else?


      4. In the addRecipe function inside mapDispatchToProps, I am dispatching many actions. Is this correct practise?



      Any other feedback for improving my Redux is most welcome.










      share|improve this question















      I made a simple React + Redux app which allows you to add and remove recipes to a list.



      Here are the user stories the app fulfills:




      User Story: I can create recipes that have names and ingredients.



      User Story: I can see an index view where the names of all the recipes are visible.



      User Story: I can click into any of those recipes to view it.



      User Story: I can delete these recipes.




      User Story: All new recipes I add are saved in my browser's local storage. If I refresh the page, these recipes will still be there.



      Code:



      import React from 'react'
      import ReactDOM from 'react-dom'
      import { connect } from 'react-redux'
      import { createStore } from 'redux'

      const ADD_RECIPE = 'ADD_RECIPE'
      const SHOW_RECIPE = 'SHOW_RECIPE'
      const EDIT_RECIPE = 'EDIT_RECIPE'
      const UPDATE_ACTIVE_NAME = 'UPDATE_ACTIVE_NAME'
      const UPDATE_ACTIVE_INGREDIENTS = 'UPDATE_ACTIVE_INGREDIENTS'
      const TOGGLE_ACTIVE_ID = 'TOGGLE_ACTIVE_ID'
      const DELETE_RECIPE = 'DELETE_RECIPE'

      const initialState = {
      activeName: '',
      activeIngredients: '',
      activeId: '',
      recipes: [
      {
      id: 1,
      name: 'Pizza',
      ingredients: 'Dough, tomato, cheese, salt, pepper, olives, mushrooms, ham.'
      },
      {
      id: 2,
      name: 'Sherpherd's Pie',
      ingredients: 'Potato, lamb'
      },
      {
      id: 3,
      name: 'Huel Shake',
      ingredients: 'Milk, huel'
      }
      ]
      }

      // action creators
      const saveStoreRecipesToLocalStorage = (state) => {
      localStorage.setItem('state', JSON.stringify(
      {...state, activeId: ""}
      ));
      }

      const getStoreRecipesFromLocalStorage = () => {
      const state = JSON.parse(localStorage.getItem('state'))
      return state.recipes.length && state
      }

      const addRecipe = (id, name, ingredients) => {
      return {
      type: ADD_RECIPE,
      payload: {
      id,
      name,
      ingredients
      }
      }
      }

      const updateActiveName = payload => {
      return {
      type: UPDATE_ACTIVE_NAME,
      payload
      }
      }

      const updateActiveIngredients = payload => {
      return {
      type: UPDATE_ACTIVE_INGREDIENTS,
      payload
      }
      }

      const toggleActiveId = id => {
      return {
      type: TOGGLE_ACTIVE_ID,
      payload: id
      }
      }

      const deleteRecipe = id => {
      return {
      type: DELETE_RECIPE,
      payload: id
      }
      }

      // reducer
      function recipes (state = getStoreRecipesFromLocalStorage() || initialState, action) {
      console.warn('action:', action)
      switch (action.type) {
      case TOGGLE_ACTIVE_ID:
      return {...state, activeId: action.payload}
      case UPDATE_ACTIVE_NAME:
      return {...state, activeName: action.payload}
      case UPDATE_ACTIVE_INGREDIENTS:
      return {...state, activeIngredients: action.payload}
      case ADD_RECIPE:
      return {...state, recipes: [...state.recipes, action.payload]}
      case DELETE_RECIPE:
      return {...state, recipes: state.recipes.filter(recipe => recipe.id !== action.payload)}
      case EDIT_RECIPE:
      return
      default:
      return state
      }
      }

      const Recipes = (props) => {
      getStoreRecipesFromLocalStorage()
      const {addRecipe, updateActiveIngredients, updateActiveName, toggleActiveId, deleteRecipe, state} = props
      const id = new Date().getTime() / 1000
      return (
      <div style={{width: 320}}>
      <form onSubmit={e => {
      e.preventDefault()
      addRecipe(id, state.activeName, state.activeIngredients)
      }}>
      <input
      type="text"
      placeholder="Name"
      value={state.activeName}
      onChange={(e) => updateActiveName(e.target.value)}
      />
      <input
      placeholder="Ingredients"
      value={state.activeIngredients}
      onChange={e => updateActiveIngredients(e.target.value)}
      />
      <button type="submit">Add Recipe</button>
      </form>
      {state.recipes.map(item => <ul key={item.name}>
      <div style={{display: 'flex', justifyContent: 'space-between'}}>
      <li onClick={() => toggleActiveId(item.id)}>
      <div>{item.name}</div>
      {state.activeId === item.id && <div>{item.ingredients}</div>}
      </li>
      <div style={{color: 'red'}} onClick={() => deleteRecipe(item.id)}>&times;</div>
      </div>
      </ul>)}

      </div>
      )
      }

      const mapStateToProps = (state) => {
      return {
      state
      }
      }

      const mapDispatchToProps = (dispatch, ownProps) => {
      return {
      addRecipe: (id, name, ingredients) => {
      if (name && ingredients) {
      dispatch(addRecipe(id, name, ingredients))
      dispatch(updateActiveName(''))
      dispatch(updateActiveIngredients(''))
      saveStoreRecipesToLocalStorage(ownProps.store.getState())
      }
      },
      updateActiveName: name => dispatch(updateActiveName(name)),
      updateActiveIngredients: ingredients => dispatch(updateActiveIngredients(ingredients)),
      toggleActiveId: id => dispatch(toggleActiveId(id)),
      deleteRecipe: id => {
      dispatch(deleteRecipe(id))
      saveStoreRecipesToLocalStorage(ownProps.store.getState())
      }
      }
      }

      const App = connect(
      mapStateToProps,
      mapDispatchToProps
      )(Recipes)

      const store = createStore(recipes, window.__REDUX_DEVTOOLS_EXTENSION__())
      const render = () => ReactDOM.render(<App store={store}/>, document.getElementById('root'))
      store.subscribe(render)
      render()


      I would like to structure the app better by splitting this file into separate files but for the sake of this question I have kept it in one file.



      Demo (adapted for codepen without localStorage features): https://codepen.io/alanbuchanan/pen/LQWKBZ



      Making this small app brought about some questions I have about Redux:




      1. I have an updateActiveName and updateActiveIngredients function because there are only these two fields that get added by the form. Would it be better instead to use an updateActiveObject and run this when either field changes? I see this as a benefit for when other fields get added, but less efficient because I will be running an onChange function for several fields that aren't changing.


      2. The naming of my action creators, reducers, and functions inside mapDispatchToProps are usually the same. For example UPDATE_ACTIVE_INGREDIENTS, updateActiveIngredients action creator and updateActiveIngredients function. Is there a better approach to this?


      3. In the addRecipe function inside mapDispatchToProps, I am validating the name and ingredients values. Should this go inside this function, or somewhere else?


      4. In the addRecipe function inside mapDispatchToProps, I am dispatching many actions. Is this correct practise?



      Any other feedback for improving my Redux is most welcome.







      react.js jsx redux






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Feb 10 at 20:01









      200_success

      128k15150412




      128k15150412










      asked Feb 10 at 19:55









      alanbuchanan

      66721325




      66721325






















          2 Answers
          2






          active

          oldest

          votes


















          0














          I've only started working with React/Redux myself, but here are my thoughts.




          1. In my system I am saving the form values to local component state until the form is saved. I have one onChange handler method which checks which form field it is and then will setState.


          2. This is something I also find with React/Redux - a lot of boilerplate and repetition to update a few pieces of data... Similar to yourself I have the Action Types / Action Creators / API Calls / Reducers / Component methods all with very similar names. I think that is just the way it is. I'm also looking to include redux-saga in our code so that potentially means even more of the same named methods.


          3. I use parsley for form validating, so that code is handled by the library. If I really needed to do further checking, I would do it in the onChange before changing the local component state.


          4. You have everything in one component at the moment for listing the recipes and adding the recipes. I would split them into separate components and then once you're finished with saving a new recipe, render the list again. Your app is very much like a To Do list app, have a look for examples of that.



          If it wasn't for the speed of react-redux, I probably wouldn't be bothered with it!



          Here's an example of a to do app that has a similar structure to my own app (which I hope is well structured lol).
          https://github.com/reactjs/redux/tree/master/examples/todomvc






          share|improve this answer































            0














            The one thing that I would change is that since you are already using react-redux library, you might as well do this -



            let store = createStore(recipes, window.__REDUX_DEVTOOLS_EXTENSION__())

            render(
            <Provider store={store}>
            <App />
            </Provider>,
            document.getElementById('root')
            )


            So that you don't have to manually subscribe like so -



            store.subscribe(render)
            render()






            About the questions that you mentioned -





            1. I have an updateActiveName and updateActiveIngredients function because there are only these two fields that get added by the form. Would it be better instead to use an updateActiveObject and run this when either field changes? I see this as a benefit for when other fields get added, but less efficient because I will be running an onChange function for several fields that aren't changing.




            This is again an opinion, but I wouldn't do that. One reason is that they don't/might not have similar types.



            An example where this might work is - say - you have a big form where you have to enter a number of dates, one for birthdate, one for date of joining the company etc. You could a function changeDate()/updateDate() which would serve as a common function to update dates.







            1. The naming of my action creators, reducers, and functions inside mapDispatchToProps are usually the same. For example UPDATE_ACTIVE_INGREDIENTS, updateActiveIngredients action creator and updateActiveIngredients function. Is there a better approach to this?




            This is fine, so long as you stick with it. You anyways don't have to worry about the ActionCreator names because, if you access the methods/functions that are defined in mapDispatchToProps() and don't directly dispatch() actions in the Component itself, you wouldn't find much problems with understanding what goes where.



            What I mean is, if you use - this.props.updateActiveIngredients() - then it is fine. However, if you use - this.props.dispatch(updateActiveIngredients()) you might get confused.






            3.In the addRecipe function inside mapDispatchToProps, I am validating the name and ingredients values. Should this go inside this function, or somewhere else?




            Technically, it is a function. You can move it to a named function, but for something this small this is alright.






            4.In the addRecipe function inside mapDispatchToProps, I am dispatching many actions. Is this correct practice?




            This is correct. You can also add a redux-thunk middleware and add an ActionCreator that returns a function instead of a simple JSON object.



            For e.g.:



            const mapDispatchToProps = (dispatch, ownProps) => {
            return {
            addRecipe: (id, name, ingredients) => {
            if (name && ingredients) {
            dispatch(addRecipe(id, name, ingredients))
            dispatch(updateActiveName(''))
            dispatch(updateActiveIngredients(''))
            saveStoreRecipesToLocalStorage(ownProps.store.getState())
            }
            }
            }
            }


            could be replaced by something like this -



            const mapDispatchToProps = (dispatch, ownProps) => {
            return {
            addRecipe: (id, name, ingredients) => dispatch(addRecipe(id, name, ingredients))
            }
            }
            // Action Creator
            addRecipe(id, name, ingredients) => {
            return (dispatch, getState) => {
            if (name && ingredients) {
            dispatch(addRecipe(id, name, ingredients))
            dispatch(updateActiveName(''))
            dispatch(updateActiveIngredients(''))
            // Get the proper state that you want using getState()
            const something = getState()
            saveStoreRecipesToLocalStorage(something)
            }
            }
            }





            share|improve this answer





















              Your Answer





              StackExchange.ifUsing("editor", function () {
              return StackExchange.using("mathjaxEditing", function () {
              StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
              StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
              });
              });
              }, "mathjax-editing");

              StackExchange.ifUsing("editor", function () {
              StackExchange.using("externalEditor", function () {
              StackExchange.using("snippets", function () {
              StackExchange.snippets.init();
              });
              });
              }, "code-snippets");

              StackExchange.ready(function() {
              var channelOptions = {
              tags: "".split(" "),
              id: "196"
              };
              initTagRenderer("".split(" "), "".split(" "), channelOptions);

              StackExchange.using("externalEditor", function() {
              // Have to fire editor after snippets, if snippets enabled
              if (StackExchange.settings.snippets.snippetsEnabled) {
              StackExchange.using("snippets", function() {
              createEditor();
              });
              }
              else {
              createEditor();
              }
              });

              function createEditor() {
              StackExchange.prepareEditor({
              heartbeatType: 'answer',
              autoActivateHeartbeat: false,
              convertImagesToLinks: false,
              noModals: true,
              showLowRepImageUploadWarning: true,
              reputationToPostImages: null,
              bindNavPrevention: true,
              postfix: "",
              imageUploader: {
              brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
              contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
              allowUrls: true
              },
              onDemand: true,
              discardSelector: ".discard-answer"
              ,immediatelyShowMarkdownHelp:true
              });


              }
              });














              draft saved

              draft discarded


















              StackExchange.ready(
              function () {
              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f187274%2fredux-recipe-list%23new-answer', 'question_page');
              }
              );

              Post as a guest















              Required, but never shown

























              2 Answers
              2






              active

              oldest

              votes








              2 Answers
              2






              active

              oldest

              votes









              active

              oldest

              votes






              active

              oldest

              votes









              0














              I've only started working with React/Redux myself, but here are my thoughts.




              1. In my system I am saving the form values to local component state until the form is saved. I have one onChange handler method which checks which form field it is and then will setState.


              2. This is something I also find with React/Redux - a lot of boilerplate and repetition to update a few pieces of data... Similar to yourself I have the Action Types / Action Creators / API Calls / Reducers / Component methods all with very similar names. I think that is just the way it is. I'm also looking to include redux-saga in our code so that potentially means even more of the same named methods.


              3. I use parsley for form validating, so that code is handled by the library. If I really needed to do further checking, I would do it in the onChange before changing the local component state.


              4. You have everything in one component at the moment for listing the recipes and adding the recipes. I would split them into separate components and then once you're finished with saving a new recipe, render the list again. Your app is very much like a To Do list app, have a look for examples of that.



              If it wasn't for the speed of react-redux, I probably wouldn't be bothered with it!



              Here's an example of a to do app that has a similar structure to my own app (which I hope is well structured lol).
              https://github.com/reactjs/redux/tree/master/examples/todomvc






              share|improve this answer




























                0














                I've only started working with React/Redux myself, but here are my thoughts.




                1. In my system I am saving the form values to local component state until the form is saved. I have one onChange handler method which checks which form field it is and then will setState.


                2. This is something I also find with React/Redux - a lot of boilerplate and repetition to update a few pieces of data... Similar to yourself I have the Action Types / Action Creators / API Calls / Reducers / Component methods all with very similar names. I think that is just the way it is. I'm also looking to include redux-saga in our code so that potentially means even more of the same named methods.


                3. I use parsley for form validating, so that code is handled by the library. If I really needed to do further checking, I would do it in the onChange before changing the local component state.


                4. You have everything in one component at the moment for listing the recipes and adding the recipes. I would split them into separate components and then once you're finished with saving a new recipe, render the list again. Your app is very much like a To Do list app, have a look for examples of that.



                If it wasn't for the speed of react-redux, I probably wouldn't be bothered with it!



                Here's an example of a to do app that has a similar structure to my own app (which I hope is well structured lol).
                https://github.com/reactjs/redux/tree/master/examples/todomvc






                share|improve this answer


























                  0












                  0








                  0






                  I've only started working with React/Redux myself, but here are my thoughts.




                  1. In my system I am saving the form values to local component state until the form is saved. I have one onChange handler method which checks which form field it is and then will setState.


                  2. This is something I also find with React/Redux - a lot of boilerplate and repetition to update a few pieces of data... Similar to yourself I have the Action Types / Action Creators / API Calls / Reducers / Component methods all with very similar names. I think that is just the way it is. I'm also looking to include redux-saga in our code so that potentially means even more of the same named methods.


                  3. I use parsley for form validating, so that code is handled by the library. If I really needed to do further checking, I would do it in the onChange before changing the local component state.


                  4. You have everything in one component at the moment for listing the recipes and adding the recipes. I would split them into separate components and then once you're finished with saving a new recipe, render the list again. Your app is very much like a To Do list app, have a look for examples of that.



                  If it wasn't for the speed of react-redux, I probably wouldn't be bothered with it!



                  Here's an example of a to do app that has a similar structure to my own app (which I hope is well structured lol).
                  https://github.com/reactjs/redux/tree/master/examples/todomvc






                  share|improve this answer














                  I've only started working with React/Redux myself, but here are my thoughts.




                  1. In my system I am saving the form values to local component state until the form is saved. I have one onChange handler method which checks which form field it is and then will setState.


                  2. This is something I also find with React/Redux - a lot of boilerplate and repetition to update a few pieces of data... Similar to yourself I have the Action Types / Action Creators / API Calls / Reducers / Component methods all with very similar names. I think that is just the way it is. I'm also looking to include redux-saga in our code so that potentially means even more of the same named methods.


                  3. I use parsley for form validating, so that code is handled by the library. If I really needed to do further checking, I would do it in the onChange before changing the local component state.


                  4. You have everything in one component at the moment for listing the recipes and adding the recipes. I would split them into separate components and then once you're finished with saving a new recipe, render the list again. Your app is very much like a To Do list app, have a look for examples of that.



                  If it wasn't for the speed of react-redux, I probably wouldn't be bothered with it!



                  Here's an example of a to do app that has a similar structure to my own app (which I hope is well structured lol).
                  https://github.com/reactjs/redux/tree/master/examples/todomvc







                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited Feb 11 at 12:48

























                  answered Feb 11 at 12:41









                  DavidC799

                  12




                  12

























                      0














                      The one thing that I would change is that since you are already using react-redux library, you might as well do this -



                      let store = createStore(recipes, window.__REDUX_DEVTOOLS_EXTENSION__())

                      render(
                      <Provider store={store}>
                      <App />
                      </Provider>,
                      document.getElementById('root')
                      )


                      So that you don't have to manually subscribe like so -



                      store.subscribe(render)
                      render()






                      About the questions that you mentioned -





                      1. I have an updateActiveName and updateActiveIngredients function because there are only these two fields that get added by the form. Would it be better instead to use an updateActiveObject and run this when either field changes? I see this as a benefit for when other fields get added, but less efficient because I will be running an onChange function for several fields that aren't changing.




                      This is again an opinion, but I wouldn't do that. One reason is that they don't/might not have similar types.



                      An example where this might work is - say - you have a big form where you have to enter a number of dates, one for birthdate, one for date of joining the company etc. You could a function changeDate()/updateDate() which would serve as a common function to update dates.







                      1. The naming of my action creators, reducers, and functions inside mapDispatchToProps are usually the same. For example UPDATE_ACTIVE_INGREDIENTS, updateActiveIngredients action creator and updateActiveIngredients function. Is there a better approach to this?




                      This is fine, so long as you stick with it. You anyways don't have to worry about the ActionCreator names because, if you access the methods/functions that are defined in mapDispatchToProps() and don't directly dispatch() actions in the Component itself, you wouldn't find much problems with understanding what goes where.



                      What I mean is, if you use - this.props.updateActiveIngredients() - then it is fine. However, if you use - this.props.dispatch(updateActiveIngredients()) you might get confused.






                      3.In the addRecipe function inside mapDispatchToProps, I am validating the name and ingredients values. Should this go inside this function, or somewhere else?




                      Technically, it is a function. You can move it to a named function, but for something this small this is alright.






                      4.In the addRecipe function inside mapDispatchToProps, I am dispatching many actions. Is this correct practice?




                      This is correct. You can also add a redux-thunk middleware and add an ActionCreator that returns a function instead of a simple JSON object.



                      For e.g.:



                      const mapDispatchToProps = (dispatch, ownProps) => {
                      return {
                      addRecipe: (id, name, ingredients) => {
                      if (name && ingredients) {
                      dispatch(addRecipe(id, name, ingredients))
                      dispatch(updateActiveName(''))
                      dispatch(updateActiveIngredients(''))
                      saveStoreRecipesToLocalStorage(ownProps.store.getState())
                      }
                      }
                      }
                      }


                      could be replaced by something like this -



                      const mapDispatchToProps = (dispatch, ownProps) => {
                      return {
                      addRecipe: (id, name, ingredients) => dispatch(addRecipe(id, name, ingredients))
                      }
                      }
                      // Action Creator
                      addRecipe(id, name, ingredients) => {
                      return (dispatch, getState) => {
                      if (name && ingredients) {
                      dispatch(addRecipe(id, name, ingredients))
                      dispatch(updateActiveName(''))
                      dispatch(updateActiveIngredients(''))
                      // Get the proper state that you want using getState()
                      const something = getState()
                      saveStoreRecipesToLocalStorage(something)
                      }
                      }
                      }





                      share|improve this answer


























                        0














                        The one thing that I would change is that since you are already using react-redux library, you might as well do this -



                        let store = createStore(recipes, window.__REDUX_DEVTOOLS_EXTENSION__())

                        render(
                        <Provider store={store}>
                        <App />
                        </Provider>,
                        document.getElementById('root')
                        )


                        So that you don't have to manually subscribe like so -



                        store.subscribe(render)
                        render()






                        About the questions that you mentioned -





                        1. I have an updateActiveName and updateActiveIngredients function because there are only these two fields that get added by the form. Would it be better instead to use an updateActiveObject and run this when either field changes? I see this as a benefit for when other fields get added, but less efficient because I will be running an onChange function for several fields that aren't changing.




                        This is again an opinion, but I wouldn't do that. One reason is that they don't/might not have similar types.



                        An example where this might work is - say - you have a big form where you have to enter a number of dates, one for birthdate, one for date of joining the company etc. You could a function changeDate()/updateDate() which would serve as a common function to update dates.







                        1. The naming of my action creators, reducers, and functions inside mapDispatchToProps are usually the same. For example UPDATE_ACTIVE_INGREDIENTS, updateActiveIngredients action creator and updateActiveIngredients function. Is there a better approach to this?




                        This is fine, so long as you stick with it. You anyways don't have to worry about the ActionCreator names because, if you access the methods/functions that are defined in mapDispatchToProps() and don't directly dispatch() actions in the Component itself, you wouldn't find much problems with understanding what goes where.



                        What I mean is, if you use - this.props.updateActiveIngredients() - then it is fine. However, if you use - this.props.dispatch(updateActiveIngredients()) you might get confused.






                        3.In the addRecipe function inside mapDispatchToProps, I am validating the name and ingredients values. Should this go inside this function, or somewhere else?




                        Technically, it is a function. You can move it to a named function, but for something this small this is alright.






                        4.In the addRecipe function inside mapDispatchToProps, I am dispatching many actions. Is this correct practice?




                        This is correct. You can also add a redux-thunk middleware and add an ActionCreator that returns a function instead of a simple JSON object.



                        For e.g.:



                        const mapDispatchToProps = (dispatch, ownProps) => {
                        return {
                        addRecipe: (id, name, ingredients) => {
                        if (name && ingredients) {
                        dispatch(addRecipe(id, name, ingredients))
                        dispatch(updateActiveName(''))
                        dispatch(updateActiveIngredients(''))
                        saveStoreRecipesToLocalStorage(ownProps.store.getState())
                        }
                        }
                        }
                        }


                        could be replaced by something like this -



                        const mapDispatchToProps = (dispatch, ownProps) => {
                        return {
                        addRecipe: (id, name, ingredients) => dispatch(addRecipe(id, name, ingredients))
                        }
                        }
                        // Action Creator
                        addRecipe(id, name, ingredients) => {
                        return (dispatch, getState) => {
                        if (name && ingredients) {
                        dispatch(addRecipe(id, name, ingredients))
                        dispatch(updateActiveName(''))
                        dispatch(updateActiveIngredients(''))
                        // Get the proper state that you want using getState()
                        const something = getState()
                        saveStoreRecipesToLocalStorage(something)
                        }
                        }
                        }





                        share|improve this answer
























                          0












                          0








                          0






                          The one thing that I would change is that since you are already using react-redux library, you might as well do this -



                          let store = createStore(recipes, window.__REDUX_DEVTOOLS_EXTENSION__())

                          render(
                          <Provider store={store}>
                          <App />
                          </Provider>,
                          document.getElementById('root')
                          )


                          So that you don't have to manually subscribe like so -



                          store.subscribe(render)
                          render()






                          About the questions that you mentioned -





                          1. I have an updateActiveName and updateActiveIngredients function because there are only these two fields that get added by the form. Would it be better instead to use an updateActiveObject and run this when either field changes? I see this as a benefit for when other fields get added, but less efficient because I will be running an onChange function for several fields that aren't changing.




                          This is again an opinion, but I wouldn't do that. One reason is that they don't/might not have similar types.



                          An example where this might work is - say - you have a big form where you have to enter a number of dates, one for birthdate, one for date of joining the company etc. You could a function changeDate()/updateDate() which would serve as a common function to update dates.







                          1. The naming of my action creators, reducers, and functions inside mapDispatchToProps are usually the same. For example UPDATE_ACTIVE_INGREDIENTS, updateActiveIngredients action creator and updateActiveIngredients function. Is there a better approach to this?




                          This is fine, so long as you stick with it. You anyways don't have to worry about the ActionCreator names because, if you access the methods/functions that are defined in mapDispatchToProps() and don't directly dispatch() actions in the Component itself, you wouldn't find much problems with understanding what goes where.



                          What I mean is, if you use - this.props.updateActiveIngredients() - then it is fine. However, if you use - this.props.dispatch(updateActiveIngredients()) you might get confused.






                          3.In the addRecipe function inside mapDispatchToProps, I am validating the name and ingredients values. Should this go inside this function, or somewhere else?




                          Technically, it is a function. You can move it to a named function, but for something this small this is alright.






                          4.In the addRecipe function inside mapDispatchToProps, I am dispatching many actions. Is this correct practice?




                          This is correct. You can also add a redux-thunk middleware and add an ActionCreator that returns a function instead of a simple JSON object.



                          For e.g.:



                          const mapDispatchToProps = (dispatch, ownProps) => {
                          return {
                          addRecipe: (id, name, ingredients) => {
                          if (name && ingredients) {
                          dispatch(addRecipe(id, name, ingredients))
                          dispatch(updateActiveName(''))
                          dispatch(updateActiveIngredients(''))
                          saveStoreRecipesToLocalStorage(ownProps.store.getState())
                          }
                          }
                          }
                          }


                          could be replaced by something like this -



                          const mapDispatchToProps = (dispatch, ownProps) => {
                          return {
                          addRecipe: (id, name, ingredients) => dispatch(addRecipe(id, name, ingredients))
                          }
                          }
                          // Action Creator
                          addRecipe(id, name, ingredients) => {
                          return (dispatch, getState) => {
                          if (name && ingredients) {
                          dispatch(addRecipe(id, name, ingredients))
                          dispatch(updateActiveName(''))
                          dispatch(updateActiveIngredients(''))
                          // Get the proper state that you want using getState()
                          const something = getState()
                          saveStoreRecipesToLocalStorage(something)
                          }
                          }
                          }





                          share|improve this answer












                          The one thing that I would change is that since you are already using react-redux library, you might as well do this -



                          let store = createStore(recipes, window.__REDUX_DEVTOOLS_EXTENSION__())

                          render(
                          <Provider store={store}>
                          <App />
                          </Provider>,
                          document.getElementById('root')
                          )


                          So that you don't have to manually subscribe like so -



                          store.subscribe(render)
                          render()






                          About the questions that you mentioned -





                          1. I have an updateActiveName and updateActiveIngredients function because there are only these two fields that get added by the form. Would it be better instead to use an updateActiveObject and run this when either field changes? I see this as a benefit for when other fields get added, but less efficient because I will be running an onChange function for several fields that aren't changing.




                          This is again an opinion, but I wouldn't do that. One reason is that they don't/might not have similar types.



                          An example where this might work is - say - you have a big form where you have to enter a number of dates, one for birthdate, one for date of joining the company etc. You could a function changeDate()/updateDate() which would serve as a common function to update dates.







                          1. The naming of my action creators, reducers, and functions inside mapDispatchToProps are usually the same. For example UPDATE_ACTIVE_INGREDIENTS, updateActiveIngredients action creator and updateActiveIngredients function. Is there a better approach to this?




                          This is fine, so long as you stick with it. You anyways don't have to worry about the ActionCreator names because, if you access the methods/functions that are defined in mapDispatchToProps() and don't directly dispatch() actions in the Component itself, you wouldn't find much problems with understanding what goes where.



                          What I mean is, if you use - this.props.updateActiveIngredients() - then it is fine. However, if you use - this.props.dispatch(updateActiveIngredients()) you might get confused.






                          3.In the addRecipe function inside mapDispatchToProps, I am validating the name and ingredients values. Should this go inside this function, or somewhere else?




                          Technically, it is a function. You can move it to a named function, but for something this small this is alright.






                          4.In the addRecipe function inside mapDispatchToProps, I am dispatching many actions. Is this correct practice?




                          This is correct. You can also add a redux-thunk middleware and add an ActionCreator that returns a function instead of a simple JSON object.



                          For e.g.:



                          const mapDispatchToProps = (dispatch, ownProps) => {
                          return {
                          addRecipe: (id, name, ingredients) => {
                          if (name && ingredients) {
                          dispatch(addRecipe(id, name, ingredients))
                          dispatch(updateActiveName(''))
                          dispatch(updateActiveIngredients(''))
                          saveStoreRecipesToLocalStorage(ownProps.store.getState())
                          }
                          }
                          }
                          }


                          could be replaced by something like this -



                          const mapDispatchToProps = (dispatch, ownProps) => {
                          return {
                          addRecipe: (id, name, ingredients) => dispatch(addRecipe(id, name, ingredients))
                          }
                          }
                          // Action Creator
                          addRecipe(id, name, ingredients) => {
                          return (dispatch, getState) => {
                          if (name && ingredients) {
                          dispatch(addRecipe(id, name, ingredients))
                          dispatch(updateActiveName(''))
                          dispatch(updateActiveIngredients(''))
                          // Get the proper state that you want using getState()
                          const something = getState()
                          saveStoreRecipesToLocalStorage(something)
                          }
                          }
                          }






                          share|improve this answer












                          share|improve this answer



                          share|improve this answer










                          answered Mar 22 at 10:50









                          yadav_vi

                          351317




                          351317






























                              draft saved

                              draft discarded




















































                              Thanks for contributing an answer to Code Review Stack Exchange!


                              • Please be sure to answer the question. Provide details and share your research!

                              But avoid



                              • Asking for help, clarification, or responding to other answers.

                              • Making statements based on opinion; back them up with references or personal experience.


                              Use MathJax to format equations. MathJax reference.


                              To learn more, see our tips on writing great answers.





                              Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                              Please pay close attention to the following guidance:


                              • Please be sure to answer the question. Provide details and share your research!

                              But avoid



                              • Asking for help, clarification, or responding to other answers.

                              • Making statements based on opinion; back them up with references or personal experience.


                              To learn more, see our tips on writing great answers.




                              draft saved


                              draft discarded














                              StackExchange.ready(
                              function () {
                              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f187274%2fredux-recipe-list%23new-answer', 'question_page');
                              }
                              );

                              Post as a guest















                              Required, but never shown





















































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown

































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown







                              Popular posts from this blog

                              Список кардиналов, возведённых папой римским Каликстом III

                              Deduzione

                              Mysql.sock missing - “Can't connect to local MySQL server through socket”