Using spread operators for redux in react? Array mapping problems?

I'm currently revising my understanding of redux and react. React components are working, and I have a knex database setup along with it. I have a reducer using the following syntax.

import { FETCH_POSTS, NEW_POST } from '../actions/types';

const initialState = {
  items: [],
  item: {}
}

export default function(state = initialState, action) {
  switch (action.type) {
    case FETCH_POSTS:
        return {
        ...state,
        items: action.payload
    };
      case NEW_POST:
      return {
        ...state,
        item: action.payload
     };
    default:
      return state;
  }
}

Here is an error I get. It doesn't seem to like the spread operator.

bundle.js:445 Uncaught Error: Module build failed (from ./node_modules/babel-loader/lib/index.js):
SyntaxError: C:/workspace/study-related-projects/apistudy7112018/1.0/client/reducers/postReducer.js: Unexpected token (18:8)

It doesnt like the current syntax Im using, which was used from this video tutorial from Traversy Media here. The tutor implements the middleware differently to how I've done it, but didn't think that would be a problem. So just incase, I decided to push to the items array like so in the reducer:

import { FETCH_POSTS, NEW_POST } from '../actions/types';

const initialState = {
  items: [],
  item: {}
}

export default function(state = initialState, action) {
  switch (action.type) {
    case FETCH_POSTS:
      return state.items.push(action.payload)
    default:
      return state;
  }
}

instead of the return object with the spread operator.

and then call dispatch in the componentWillMount() function in react..

Which turned out fine, however now it has become more difficult to map the array for printing out the data in a component.

enter image description here

If I console log the this.props.payload.posts, I recieve the items but Im unsure if I can access it because the next array after posts has no name, just number 0. I tried this.props.payload.posts[0], but that didn't seem to work. This is giving me trouble mapping the data with the map array function.

Generally, If all is successful I can then use mapToProps function, then:

this.props.items.posts.map(post) => {
  return post.name
})

But I've hit a wall with these two solution. This problem came about due to me trying to implement a different way of using redux, as opposed to the way I was used to before. This is all for my own study and training.

Could anyone help me understand these two problems? One is that, javascript doesn't like the spread operator syntax I'm using and spits back that error. Second is, trying to get to the raw data through the items array. If anyone could help me out, I'd really appreciate it. Thanks.

Edit: I may put up a git repo in a bit so everyone can see the code I'm working on.

2 answers

  • answered 2018-11-08 08:48 Егор Ересько

    for example, from the first code I would venture to suggest that action.payload is an array so in the second case, you need to push the contents of the array

    case FETCH_POSTS:
      return state.items.push(...action.payload)
    

    but I also recommend not to use mutate the state

  • answered 2018-11-08 09:23 Ryan

    Assuming that you're using Babel and webpack to transpile and bundle your source code respectively, it's important to note that by default the spread operator in ES2015 is not supported for objects, only arrays; support for object spread operators is still a Stage 3 proposal in TC39.

    To support objects you need to use the Babel plugin @babel/plugin-proposal-object-rest-spread (for Babel 7). That should take care of the Unexpected token error.

    For your other example with push, I recommend against using array methods that mutate the array. It goes against one of the three fundamental principles of Redux, regarding pure functions. Your reducers should be pure to keep your state immutable, as each change to your state (dispatched action) represents a snapshot of your state.

    Instead of using push for arrays, you can use the spread operator:

    return {
      ...state,
      items: [
        ...state.items,
        action.payload,
      ],
    };
    

    (or something to that effect)

    Another note: don't rely on componentWillMount() for too much longer; it was deprecated in React 16.3 and will be removed entirely in React 17. See https://reactjs.org/docs/react-component.html#unsafe_componentwillmount for more information. If you're fetching data through AJAX or some other asynchronous method, it's better to use componentDidMount() instead.