0

I'm learing redux with react. I know that to rerender the tree you have to subscribe to some function and dispatch the action, I've done this

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

render(store)

store.subscribe( () => {
    render(store)
})

The dispatch works perfectly, I will not show the code because it does not matter in the way that the problem is about the time when I am truing to load data from the redux store using connect and there is 2 ways, of dispatching to the store, first:

state.articles.push({ title: action.article.title, id: action.article.id })
return state

second:

return Object.assign({}, state, {
            articles: state.articles.concat({
                id: action.article.id,
                title: action.article.title
            })
        });

And the problem is that only second one works, saying works I mean it updates the LIST component and maps throw redux state

may be need to understand the problem, LIST component:

const mapStateToProps = state => {
  return { articles: state.root.articles }
}

const ConnectedList = ({ articles }) => (
  <ul className="list-group list-group-flush">
    {articles.map(el => (
      <li className="list-group-item" key={el.id}>
        {el.title}
      </li>
    ))}
  </ul>
)

export default connect(mapStateToProps)(ConnectedList)
  • 2
    you aren't supposed to directly modify state. Using push on state directly modifies it. instead, use concat and store it in a new variable then return that variable. – tytyf Aug 13 '19 at 22:11
  • Well, I have read about that but what's problem with the first one, because when I am accesing the state from the **render(store)** using **getState()*** it actually updates the state – Vladislav Kruglikov Aug 13 '19 at 22:14
  • 1
    You should read the article in the redux faq: https://redux.js.org/faq/immutable-data – Håken Lid Aug 13 '19 at 22:15
  • 2
    When you call `render` you force rendering of the entire react app. Redux-react is much more efficient, it will only rerender the components whose props have changed. But when you use Array.push to mutate state.articles, it has not changed (redux does a shallow compare, so it will not detect a mutation). – Håken Lid Aug 13 '19 at 22:19
  • @Håken Lid So you mean that whe n i do push method redux will think that only the array changed and it is not going to update the component, well I will try now to change hole state? – Vladislav Kruglikov Aug 13 '19 at 22:21
  • @Håken Lid Well, that does not help, I created the **a** variable inside of state object and changed it when I was pushing to the array, nothing is changed.... :( – Vladislav Kruglikov Aug 13 '19 at 22:24
  • Don't use `Array.push` in your reducer functions. – Håken Lid Aug 13 '19 at 22:29
  • where is your reducer and where are you creating the store. – tytyf Aug 13 '19 at 22:29
  • I understand it but I still don't understand why at all, I want to know that deeply – Vladislav Kruglikov Aug 13 '19 at 22:30
  • @21x37, This part works fine, so that why i have not added it here – Vladislav Kruglikov Aug 13 '19 at 22:31
  • Possible duplicate of [Redux: Why is avoiding mutations such a fundamental part of using it?](https://stackoverflow.com/questions/37531909/redux-why-is-avoiding-mutations-such-a-fundamental-part-of-using-it) or [My Redux state has changed, why doesn't React trigger a re-render?](https://stackoverflow.com/questions/39513753/my-redux-state-has-changed-why-doesnt-react-trigger-a-re-render) – Håken Lid Aug 13 '19 at 22:33
  • Thanks @Håken Lid, the threads provided by have helped me and I understand the idea of 'not-mutating '! – Vladislav Kruglikov Aug 13 '19 at 22:36

1 Answers1

0

There is no way to use array.push(), because Redux need new state, completely new whole state to update the component that you hav esubscribed to, so when we are doing push function we are keeping same state, the only thing we change is array inside of its state, so the solution is to create **new object and unite with an old object, that will have the new array :D Some code:

 let absolutelyNewState = Object.assign({}, state, {
            articles: state.articles.concat({
                id: action.article.id,
                title: action.article.title
            })
 })

 return absolutelyNewState