функция map (item) не может передать «item» компоненту JSX в качестве реквизита после реализации redux в react

#javascript #reactjs #react-native #redux #react-redux

#javascript #reactjs #react-native #redux #react-redux

Вопрос:

Я пытаюсь реализовать redux в своем приложении react. До сих пор я создал 4 действия для управления «элементами» моих приложений. Первые три; GET_ITEMS, DELETE_ITEM и ADD_ITEM работают отлично и легко сочетаются с моим существующим приложением react. Четвертый «TOGGLE_ITEM» фактически функционирует и переключает элементы, но каким-то образом сломал мой существующий компонент react. Я получаю неопределенную ошибку «item» в моем Items.js досье. Вот код, строки со звездочками имеют большое значение:

  1. Корневой компонент = Musiclist.js:
 class MusicList extends Component {

    componentDidMount() {
        this.props.getItems();
        *console.log(this.props.item.items)*
        // Console log returns the proper items array that gets passed down below to the Items component
    }

    toggle = (id) => {
        *this.props.toggleItem(id)*
        // Pings the item reducer and executes the toggle function, which functions properly
    }

    delItem = (id) => {
        this.props.deleteItem(id)
    }

    addItem = (url) => {
        this.props.addItem(url)
    }

    render() {

        *const { items } = this.props.item*
        // Same as saying this.props.item.items

        return (
            
            <div>

                <AddItem addItem={this.addItem}/>

                *<Items items = {items} toggle = {this.toggle} delItem = {this.delItem} />*
                // Takes in the array items as a prop and the function toggle() as a prop

            </div>

        )
        
    }

}

MusicList.propTypes = {
    getItems: PropTypes.func.isRequired,
    deleteItem: PropTypes.func.isRequired, 
    addItem: PropTypes.func.isRequired,
    toggleItem: PropTypes.func.isRequired,
    item: PropTypes.object.isRequired
    
}

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

export default connect(mapStateToProps, { getItems, deleteItem, addItem, toggleItem})(MusicList);
  

Редуктор = itemReducer.js:

Кажется, это работает отлично и работает так, как должно. Я также не вижу никаких видимых причин, по которым это повлияло бы на компонент Items, поэтому, скорее всего, это красное слушание… Но у меня начались проблемы только после его реализации.

 case TOGGLE_ITEM:
   return {
      items: state.items.map(item => {
         if(item.id === action.payload) {
            item.isOpen = !item.isOpen
         }
      })
   }
  

Проблемный компонент = Items.js:

Компонент выдает ошибку.

 import React, { Component } from 'react';
import Item from "./Item";
import PropTypes from "prop-types";

class Items extends Component {

    componentDidMount() {
        // Console logs the same array as the one in MusicList.js
        *console.log(this.props.items)*
        this.props.items.map((item) => (
            // Console logs as it's supposed to, maps the items and prints them, no "item undefined" error
            console.log(item)
        ))
    }
    
    render() {

        return this.props.items.map((item) => (

            <div>

                // "item" is undefined on this line despite the map function defining it above. 
                // I did not change any code here when implementing redux, yet there was no error before redux.
                *<Item key = {item.id} item = {item} toggle = {this.props.toggle} delItem = {this.props.delItem} isOpen = {item.isOpen}/>*

            </div>

            ));
    }
}

// PropTypes
Items.propTypes = {
    items: PropTypes.array.isRequired
}

export default Items;
  

Любая помощь приветствуется!

Комментарии:

1. Правильное обновление переключения также должно копировать любое существующее состояние и возвращать новую ссылку на объект item в сопоставлении, т. return { ...state, item: state.items.map(item => item.id === action.payload ? { ...item, isOpen: !item.isOpen } : item), } Е.. Поскольку у вас есть проблема только после реализации TOGGLE_ITEM , можно ли предположить, что код пользовательского интерфейса в порядке, пока вы не попытаетесь переключить элемент? Можете ли вы предоставить более полный пример кода и шаги воспроизведения? Запущенный codesandbox был бы действительно полезен, чтобы мы могли отладить его в реальном времени.

Ответ №1:

функции map в reducer потребуется оператор return

 case TOGGLE_ITEM:
   return {
      ...state,
      items: state.items.map(item => {
         if(item.id === action.payload) {
            item.isOpen = !item.isOpen
         }
         return item;
      })
   }
  

Это решит проблему. И всегда распределяйте состояние, а затем добавляйте запятую, а затем измененные пары ключ-значение

Комментарии:

1. Часть «return item» решила эту проблему. Но какова цель возврата состояния с помощью «… state»?

2. Когда вы используете ...state (деструктурирование объекта ES6, вы также можете использовать Object.assign) в качестве возврата функции reducer , тогда она создает объект со всеми данными, которые находятся в этом редукторе, а затем упомянутые ключи добавляются / заменяются на этот объект. таким образом, ваши другие данные остаются нетронутыми, но если вы не используете ...state , то ваш редуктор содержит только объект с упомянутыми парами ключ-значение. Ознакомьтесь с этим документом redux.js.org/basics/reducers#handling-actions

Ответ №2:

Хорошо ли это написано в вашем приложении? Эта строка кода должна быть:

 <Item key={item.id} item={item} toggle={this.props.toggle} delItem={this.props.delItem} isOpen={item.isOpen}/>
  

Между реквизитом и фактическим значением не должно быть пробелов

Комментарии:

1. К сожалению, это не сработало, я почти уверен, что пробел либо косметический, либо компилятор исправляет его.