使用React Redux显示的记录的ID冲突

时间:2018-11-04 22:25:39

标签: reactjs redux

React-Redux 代码用于每次单击Loadmore按钮并能正常工作时从数据库中加载更多内容。

初始内容显示为2,当您单击loadmore按钮时,更多的记录将以2装入。

我后来发现,每当我注销并再次登录时,每次单击“加载更多”按钮并加载更多内容时, 按钮单击时已加载的那些记录仍将在页面上,因此导致记录显示(id)冲突 导致以下错误

bundle.js:856警告:遇到两个具有相同密钥1的孩子。键应该是唯一的,以便组件可以维护  他们的身份跨更新。非唯一键可能会导致子代重复和/或被忽略-这种行为 不支持,并且可能会在将来的版本中更改。

请如何防止此记录显示冲突...

我认为导致此问题的原因是通过loadmore按钮将旧记录/默认记录与新加载的记录的串联 在我的 user.reducer.js 中,我有下面的代码

//concatenate the old item with new item

case userConstants.GETALL_REQUEST:
  return {
    ...state,
    loading: true
  };
case userConstants.GETALL_SUCCESS:
  return {
    loading: false,
    error: null,
// items: action.users
    items: [ ...(state.items || []), ...action.users ]
  }; 

这是主页组件

import React from "react";
import { Link } from "react-router-dom";
import { connect } from "react-redux";

import { userActions } from "../_actions";

class HomePage extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      row_pass: 0
    };
    this.row = 0;
    this.rowperpage = 2;
    this.buttonText = "Load More";
    this.loadMore = this.loadMore.bind(this);
  }

  componentDidMount() {
    this.props.dispatch(userActions.getAll(this.row));
  }

  loadMore() {
    this.row += this.rowperpage;
    alert("loading" + this.row);
    this.props.dispatch(userActions.getAll(this.row));
    this.buttonText = "Load More";
  }




  render() {
    const { user, users } = this.props;
    return (
      <div
        style={{ background: "red" }}
        className="well col-md-6 col-md-offset-3"
      >
        <h1>
          Hi{user.message}! {user.token}
        </h1>
        <p>You're logged in with React!!</p>
        <h3>All registered users:</h3>
        {users.loading && <em>Loading users...</em>}
        {users.error && (
          <span className="text-danger">ERROR: {users.error}</span>
        )}
        {users.items && (
          <ul>
            {users.items.map((user, index) => (
              <li key={user.id}>
                {user.firstName + " " + user.lastName}:
                <span>
                  {" "}
                  - <a>home</a>
                </span>
              </li>
            ))}
            {this.finished}
          </ul>
        )}
        <p>
          <a className="pic" onClick={this.loadMore}>
            {this.buttonText}
          </a>
        </p>
      </div>
    );
  }
}

function mapStateToProps(state) {
  const { users, authentication } = state;
  const { user } = authentication;
  return {
    user,
    users
  };
}

const connectedHomePage = connect(mapStateToProps)(HomePage);
export { connectedHomePage as HomePage };

这是 user.action.js

function getAll(row) {
    return dispatch => {
        dispatch(request(row));

        userService.getAll(row)
            .then(
                users => dispatch(success(users)),
                error => dispatch(failure(error.toString()))
            );
    };

user.reducer.js 代码

import { userConstants } from '../_constants';

export function users(state = {}, action) {
  switch (action.type) {

//concatenate the old item with new item

case userConstants.GETALL_REQUEST:
  return {
    ...state,
    loading: true
  };
case userConstants.GETALL_SUCCESS:
  return {
    loading: false,
    error: null,
// items: action.users
    items: [ ...(state.items || []), ...action.users ]
  };

    case userConstants.GETALL_FAILURE:
      return { 
        error: action.error
      };


    default:
      return state
  }
}

1 个答案:

答案 0 :(得分:2)

我认为解决此问题的最佳方法是注销时重置Redux存储。

我说这是因为此错误消息不是您遇到的唯一问题。 您可能在屏幕上显示重复的用户。 您可能遇到的另一个问题是,如果登录的用户与注销的用户不同,那么在这种情况下,您会将一个用户的数据显示给另一个用户,但这可能不是您的应用程序遇到的问题,具体取决于您评估。

如果您要在用户注销时重置存储,我建议您阅读this another answer

如果您不想这样做,我可以想象两种解决方法。

  • 首先是在加载初始用户之前,在componentDidMount中重置这些用户。

    要做到这一点,您的减速器中将需要这样的东西

    case userConstants.RESET:
      return {
        loading: false,
        error: null,
        items: []
      };
    

    ,并且还有与此匹配的操作。之后,只需使用类似componentDidMount

  • 的内容从this.props.dispatch(userActions.reset());分派该操作
  • 第二种解决方法是在constructor中根据用户数量设置行属性,使用类似this.row = props.users.items.length;

请记住,我建议您使用第一种解决方案,在注销时重置整个商店