Конфликты идентификаторов для отображаемых записей с использованием реагирования - PullRequest
0 голосов
/ 05 ноября 2018

Этот код React-Redux использовался для загрузки большего количества контента из базы данных при каждом нажатии кнопки 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 голосов
/ 05 ноября 2018

Я думаю, что лучший подход к этой проблеме - сбросить хранилище при выходе из системы.

Я говорю это, потому что это сообщение об ошибке - не единственная ваша проблема. Вы, вероятно, отображаете дублированных пользователей на экране. Другая проблема, с которой вы можете столкнуться, заключается в том, что пользователь, который входит в систему, не совпадает с тем, кто выходит из системы, поэтому в этом случае вы будете показывать данные одного пользователя другому, но, возможно, это не проблема для вашего приложения, это Вы оцениваете.

Если вы хотите сбросить хранилище, когда пользователь выходит из системы, я рекомендую прочитать это еще один ответ .

Если вы не хотите этого делать, я представляю 2 обходных пути.

  • Первый - это сброс этих пользователей в componentDidMount перед загрузкой начальных пользователей.

    Для этого вам понадобится что-то подобное в вашем редукторе

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

    , а также есть действие, которое соответствует этому. После этого просто отправьте это действие из componentDidMount с чем-то вроде this.props.dispatch(userActions.reset());

  • Второй обходной путь заключается в установке свойства строки на основе количества пользователей в constructor с чем-то вроде this.row = props.users.items.length;

Просто помните, я предлагаю вам выбрать первое решение, сбрасывающее весь магазин при выходе из системы

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...