Christian Lessard
Christian Lessard

Reputation: 425

Pushing Data Into My Redux State

Right now I am mapping over an array with an endpoint to my API. From there I am taking every link and calling a get request on each thing I map over. My issue is that I am not able to save everything into my redux state. I have tried using concat and push to take everything and put it all in one array in my redux state.

MomentContent.js:

componentDidMount () {

      this.props.photos.map(photo => {
        this.props.fetchPhoto(this.props.token, photo)}
      )
    }

index.js (actions):

export const fetchPhoto = (token, photo) => dispatch => {
  console.log('right token')
  console.log(token);
  fetch(photo, {
    method: 'GET',
    headers: {
      'Accept': 'application/json',
      'Content-Type': 'application/json',
      'Authorization': `Token ${token}`,
    }
  })
  .then(res => res.json())
  .then(parsedRes => {
    console.log('photo data')
    console.log(parsedRes)
    dispatch(getPhoto(parsedRes))
  })
}

export const getPhoto = (photo) => {
  console.log('RES')
  console.log(photo)
  return {
    type: GET_PHOTO,
    photo: photo
  }
}

When I use concat (reducer):

import {
  GET_PHOTO
} from '../actions';

const initialState = {
  photo: []
}

const photoReducer = (state = initialState, action) => {
  switch(action.type) {
    case GET_PHOTO:
      return {
        ...state,
        photo: initialState.photo.concat([action.photo])
      }

    default:
      return state;
  }
}

export default photoReducer

enter image description here

When I use push (reducer):

import {
  GET_PHOTO
} from '../actions';

const initialState = {
  photo: []
}

const photoReducer = (state = initialState, action) => {
  switch(action.type) {
    case GET_PHOTO:
      return {
        ...state,
        photo: initialState.photo.push([action.photo])
      }

    default:
      return state;
  }
}

export default photoReducer

enter image description here

UPDATE (another issue):

I was able to get it to work with :

return {
        ...state,
        photo: [...state.photo, action.photo]
      }

The issue now is that every time I refresh the same data is pushed again, so everything multiplies. Is there a way to fix this?

Upvotes: 5

Views: 6921

Answers (4)

Andrew Lam
Andrew Lam

Reputation: 3804

If action.photo is an array, no need to wrap it with additional [].

If you want the newly fetched photo array to combined with existing photo array in the Redux state, use state.photo.push instead of initialState.photo.push.

case GET_PHOTO:
      return {
        ...state,
        photo: state.photo.push(action.photo)
      }

Upvotes: 1

Pritish Vaidya
Pritish Vaidya

Reputation: 22189

You need to merge your updatedState and not initialState to the reducer in order to update

Either using concat:

return {
  ...state,
  photo: state.photo.concat([action.photo])
}

or using spread operator

return {
  ...state,
  photo: [...state.photo, action.photo]
}

Upvotes: 5

Shubham Khatri
Shubham Khatri

Reputation: 281726

Javascript push method on array return you the new size of the array and hence it won't work correctly.

what you need is to use concat or spread-syntax

case GET_PHOTO:
  return {
    ...state,
    photo: initialState.photo.concat([action.photo])
  }

or

case GET_PHOTO:
  return {
    ...state,
    photo: [...initialState.photo, action.photo]
  }

Upvotes: 0

Henrique Viana
Henrique Viana

Reputation: 680

the push does not work correctly in redux, the ideal is to use the spread operator to concatenate the arrays

return {
     ... state,
     photo: [... initialState.photo, action.photo]
}

Upvotes: 3

Related Questions