Изменения, внесенные в один элемент списка, затрагивают все элементы списка - PullRequest
0 голосов
/ 24 июня 2019

Мне нужно отобразить список пользователей, и при нажатии кнопки я хочу отобразить текст внутри кнопки.UserHeader - это компонент, который я импортирую из своего списка записей (PostList).Я понимаю, что действие воздействует на все элементы списка после того, как я нажимаю кнопку, и я думаю, что это потому, что массив состояний редуктора заполняется записью, и каждый раз, когда я отображаю UserHeader, он отображает текст внутри кнопки.Я хочу, чтобы текст отображался только в элементе списка, с которым я уже имею дело, а не во всем списке.Пожалуйста, помогите мне, как я могу сделать это с редуксом.Я ссылаюсь на функцию selectPost () onClick кнопки на UserHeader

// reducers.js

export const Reducer_posts = (state=[], action) => {
  switch (action.type){
    case 'FETCH_POSTS':
      return action.payload
    default:
      return state;
  }

};

export const Reducer_users = (state=[], action) => {
  switch (action.type){
    case 'FETCH_USER':
      return [...state, action.payload];
    default:
      return state;
  }
};

export const Reducer_select = (state=[], action) => {
  switch (action.type){
    case 'SELECT_POST':
      return action.payload;

    case 'DELETE_SELECT':
      return null;

    default:
      return state;
  }
};


//UserHeader.js

import React from 'react';
import { connect } from 'react-redux';
import { fetchUser, selectPost, deleteSelect } from '../actions';

class UserHeader extends React.Component {

  componentDidMount () {
    this.props.fetchUser(this.props.userId);
  }


  render() {
    console.log(this.props.select)
    if(!this.props.user) {
      return <div> Loading... </div>
    }

      return <button onClick={this.props.selectPost} className="header"> {this.props.select} </button>


  }
}


const mapStateToProps = (state, ownProps) => {
  return {
    user: state.users.find(user => user.id === ownProps.userId),
    select: state.select
   };
}

export default connect(mapStateToProps, { fetchUser, selectPost, deleteSelect })(UserHeader);


//PostList.js

import React from 'react';
import { connect } from 'react-redux';
import { fetchPosts, selectPost } from '../actions';
import UserHeader from './UserHeader'

class PostList extends React.Component {

  componentDidMount(){
    this.props.fetchPosts();
  }

  renderList() {
    return this.props.posts.map(post => {
      return (

        <div className = "item" key={post.id}>
          <i className="large middle aligned icon user" />
            <div className="content">
              <div className = "description">
                <h2> {post.title} </h2>
                <p> {post.body} </p>
              </div>

              <UserHeader userId = {post.userId}/>
            </div>
        </div>

      )
    })
  }

  render(){
    return <div className = "ui relaxed divided list"> {this.renderList()} </div>;
  };
}

const mapStateToProps = state => {
  return { posts: state.posts, select: state.select };
};

export default connect( mapStateToProps, { fetchPosts, selectPost })(PostList);

1 Ответ

0 голосов
/ 24 июня 2019

Вы должны хранить элементы состояния с идентификатором, таким образом, вы можете управлять им так, как вам нравится.Пример

// Let's imagine that this is your initial state. State here is an object of an x 
// object that contains n-object that represents your button.
//
const state = {
    myButtons: [
        {
            id: "unique_id",
            .
            .
        },
        {...}
    ],
    selectedBtn: -1,
}

В этом сценарии вы можете легко получить нужную кнопку для передачи идентификатора через действие, и таким образом редуктор будет выглядеть примерно так:

export const Reducer_posts = (state=[], action) => {
  switch (action.type){
    case 'FETCH_POSTS':
      const newState = Object.assign({}, state);
      newState.myButtons.concat(action.payload)
      return Object.assign({}, newState)
    default:
      return state;
  }

};

export const Reducer_select = (state=[], action) => {
  switch (action.type){
    case 'SELECT_POST': // I think this is fired on click on a button 
      const newState = Object.assign({}, state);
      newState.selectedBtn = action.payload.btnId;
      return Object.assign({}, newState);
    case 'DELETE_SELECT': // when you have to delete a button
      const newState = Object.assign({}, state);
      newState.myButtons = 
      newState.myButtons.filter((el) => el.id !== action.payload.id)
      return Object.assign({}, newState);

    default:
      return state;
  }
};

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

...