Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How prevent duplicated list object in react redux

I have a duplicating problem on my component which i get some dummy data from api.

Which following approach everything works well but when i change route and go to another page and back to page where i list my users object. Every time there is a duplicated list of my object. How i can prevent it?

here is my component:

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux' 
import {getAllUsers} from '../actions/user'

class users extends Component {
  componentDidMount() {
    this.props.getAllUsers()
  }

  render() {
    let usersList = this.props.users.map(user => <li key={user.id}>{user.name}</li>)

    return (
      <div>
        <h1>user list</h1>
        <ul>
          {usersList}
        </ul>
      </div>
    )
  }
}

const mapStateToProps = state => ({
  users: state.users
})


function mapDispatchToProps(dispatch) {
  return {
    getAllUsers: bindActionCreators(getAllUsers, dispatch)
  }
} 

export default connect(mapStateToProps, mapDispatchToProps)(users)

here is my reducer:

import { FETCH_USERS } from '../actions/user'

let initialState = []

export default (state = initialState, action) => {
    switch (action.type) {
        case FETCH_USERS:
            return [...state, ...action.payload]
        default:
            return state
    }
}

and here is my action:

export const FETCH_USERS = 'FETCH_USERS';

export const getAllUsers = () => {
    return(dispatch) => {
        fetch('https://jsonplaceholder.typicode.com/users')
        .then(res => res.json())
        .then(users => {
            dispatch({
                type: FETCH_USERS,
                payload: users
            })
        })
    }
}
like image 768
user3348410 Avatar asked Feb 11 '19 15:02

user3348410


1 Answers

There are a few options available to you at the moment:

  1. Evaluate whether you need to carry out the API request. If you've already made the request, can you just rely upon previously cached data in your Redux store, or do you have to rely on new users being fetched every time the component mounts?
componentDidMount() {
    if (!this.props.users.length) {
        this.props.getAllUsers();
    }
}
  1. If you need to fetch new data every time the component mounts, why not just clear the data in the Redux store when the component unmounts? E.g.

Component:

componentWillUnmount() {
    this.props.clearUsers();
}

Reducer:

import { FETCH_USERS, CLEAR_USERS } from '../actions/user'

let initialState = []

export default (state = initialState, action) => {
    switch (action.type) {
        case FETCH_USERS:
            return [...state, ...action.payload]
        case CLEAR_USERS:
            return initialState
        default:
            return state
    }
}

There are a few others options to investigate, but that should hopefully solve your issue :)

Edit:

As pointed out in comments, the author's reducer is a little all over the place. I'd look to refactor the reducer to something along the lines of:

import { FETCH_USERS } from '../actions/user'

const initialState = {
    users: [],
}

export default (state = initialState, action) => {
    switch (action.type) {
        case FETCH_USERS:
            return {
                ...state,
                users: [...action.payload],
            }
        default:
            return state
    }
}

This would solve the issue of the users being duplicated each time the component mounts, whilst ensuring the reducer can be expanded upon in the future without risking the entirety of the state being replaced.

like image 168
tombraider Avatar answered Sep 24 '22 17:09

tombraider