代码之家  ›  专栏  ›  技术社区  ›  user3348410

如何防止react redux中的重复列表对象

  •  1
  • user3348410  · 技术社区  · 5 年前

    我的组件上有一个复制问题,我从API获取了一些虚拟数据。

    下面的方法可以很好地工作,但是当我更改路由并转到另一个页面,然后返回到列出我的用户对象的页面时。每次我的对象有一个重复的列表。我怎样才能阻止它?

    这是我的组件:

    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)
    

    这是我的减速器:

    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
        }
    }
    

    下面是我的行动:

    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
                })
            })
        }
    }
    
    4 回复  |  直到 5 年前
        1
  •  2
  •   tombraider    5 年前

    目前有几个选项可供选择:

    1. 评估您是否需要执行API请求。如果您已经提出了请求,那么您可以只依赖Redux存储中以前缓存的数据,还是每次装载组件时都必须依赖于提取的新用户?
    componentDidMount() {
        if (!this.props.users.length) {
            this.props.getAllUsers();
        }
    }
    
    1. 如果每次安装组件时都需要获取新数据,为什么不在卸载组件时清除Redux存储区中的数据呢?例如。

    组件:

    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
        }
    }
    

    还有一些其他的选择要调查,但这应该能解决您的问题:)

    编辑:

    正如评论中指出的,作者的减速器有点到处都是。我希望将reducer重构为以下内容:

    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
        }
    }
    

    这将解决每次安装组件时用户都会被复制的问题,同时确保将来可以扩展减速器,而不会危及整个状态被替换的风险。

        2
  •  1
  •   Alexis    5 年前

    给你打电话 fetchUser 每次组件 mounting . 当你 router 更改组件的路径 unmount 在返回后重新安装 取用者 再打电话。

    在你的内心 FETCH_USERS 操作,而不是用新数据替换旧数据,而是将新数据推送到当前状态。

    您的问题将通过更换来解决 [...state,...action.payload] 通过 [...action.payload]

        3
  •  0
  •   user2343647    5 年前

    只要您的状态只有用户,Alexis建议就可以正常工作。一旦您将添加更多的属性,这将不再工作,因为它清除了整个状态。

    在fetch用户案例中尝试类似的方法:

    让newstate=…state

    newstate.users=[];

    newstate.users.push(action.payload);

    返回新闻状态;

        4
  •  0
  •   JPritchard9518    5 年前

    问题是,每次点击reducer中的fetch用户案例时,它都会在现有数据(state)的基础上附加额外的数据(action.payload)。因为每次装载组件时都会发生这种情况,所以它会频繁地将旧数据追加到数组中。以下是详细解释的情况:

    如果您的有效载荷等于数组[“id1”,“id2”],那么第一次装载组件时,该组件将进入

    state = ["id1", "id2"]
    

    下一次装载组件时,用户数组仍然等于[“id1”、“id2”],可能添加了新的用户,或者不再存在某些用户。假设还添加了“ID3”。减速器接受这个并将其附加到以前的状态:

    state = ["id1", "id2"]
    action.payload = ["id1", "id2", "id3"]
    

    所以…

    return [...state, ...action.payload] = [ "id1", "id2", "id1", "id2", "id3" ]
    

    添加重复。

    要解决这个问题,您只需要用有效负载填充状态,而不必保持以前的状态,因为在不筛选以前存在的用户的情况下再次检索用户列表。

    return [...action.payload]
    

    减速器现在应该如下所示:

    import { FETCH_USERS } from '../actions/user'
    
    let initialState = []
    
    export default (state = initialState, action) => {
        switch (action.type) {
            case FETCH_USERS:
                return [...action.payload]
            default:
                return state
        }
    }