TypeError: Невозможно прочитать свойство 'map' из undefined и обойти - PullRequest
0 голосов
/ 03 апреля 2020

существует объект contactBook, определенный ниже. Я отправляю его в архив и получаю обратно в том же формате.

{“Book1” : [{name: “Bob”},{name, “Jane”}, {name, “Mary”]}

Я намеревался перенести его в список имен

import React, {Component} from 'react'
import {bindActionCreators} from "redux";
import * as actions from "../redux/actions";
import {withRouter} from 'react-router'
import {connect} from 'react-redux'

class ListContactComponent extends Component {
    constructor(props) {
        super(props);
        this.state = {
            message: null
        };
    }

    componentDidMount() {
        this.props.startLoadingContacts(this.props.match.params.bookName);
    }


    addContactClicked = () => {
        this.props.history.push({
            pathname: `/addressBook/contact/`,
            state: this.state.bookName
        })
    };

    render() {
        let contacts = Object.values(this.props.contacts).flat();
        return (
            <div className="container">
                <h3>All Contacts</h3>
                {this.state.message && <div class="alert alert-success">{this.state.message}</div>}
                <div className="container">
                    <table className="table">
                        <thead>
                        <tr>
                            <th>Name</th>
                            <th>Phone Number</th>
                        </tr>
                        </thead>
                        <tbody>
                        {
                            contacts.map(
                                (contact, index) =>
                                        <tr key={index}>
                                            <td>{contact.name}</td>
                                            <td>{contact.phoneNumber}</td>
                                        </tr>
                                )
                        }
                        </tbody>
                    </table>

                    <div className="row">
                        <button className="btn btn-success" onClick={this.addContactClicked}>Add</button>
                    </div>
                </div>
            </div>
        )
    }
}

function mapStateToProps(state) {
    return {
        contacts: state.contacts
    }
}

function mapDispatchToProps(dispatch) {
    return bindActionCreators(actions, dispatch)
}

const connectedContactList = withRouter(connect(mapStateToProps, mapDispatchToProps)(ListContactComponent));
export {connectedContactList as ListContactComponent};
  1. , если я use:

    contacts = contactsBook [Book1]

Я получил TypeError: Невозможно прочитать свойство 'map' из неопределенного

в чем причина этой ошибки и как это исправить?

, если я не использую возражение, возвращенное из редукса, оно просто работает нормально. Я действительно не знаю, в чем разница?

Действия:

export function startLoadingContacts(addressBookName) {
    return (dispatch) => {
        return AddressBookDataService
            .retrieveContacts(addressBookName)
            .then(
                (response) => {
                    let contacts = {};
                    contacts[addressBookName] = response.data;
                    dispatch(loadContacts(contacts))
                }).catch((error) => {
                console.log(error)
            })
    }
}

export function loadContacts(contacts) {
    return {
        type: 'LOAD_CONTACTS',
        contacts
    }
}

Редуктор:

function contacts(state = {}, action) {
    switch (action.type) {
        case 'ADD_CONTACT':
            return "....";
        case 'LOAD_CONTACTS':
            return action.contacts;
        default:
            return state
    }
}
  • консольный журнал:

               contactsBook:
    
                 {Book1: Array(3)}
    
                        Book1: Array(3)
    
                            0: {name: "Bob"}
 
    
                            1: {name: "Jane"}
 
    
                            2: {name: "Mary"}
   
    
                             length: 3
     
    
                        __proto__: Array(0)
 
    
                        __proto__: Object
    
    
    
               contacts:
    
                     (3) [{…}, {…}, {…}]
    
                         0: {name: "Bob"}
       
    
                         1: {name: "Jane"}
       
    
                         2: {name: "Mary"}
      
    
                         length: 3
  
    

    или

  • если я использую: contacts = Object.values(contactsBook), вывод отсутствует.

при использовании JSON .stringy (контакты),

это печатает:

[[ {name: "Bob"}
,..]] rather than [{name: "Bob"},..
 ]

В этом случае, как избавиться от внешнего []?

если смоделировать преобразователь данных = [[data]], я могу удалить внешний слой с помощью преобразователя [0].

, но он не работает для

contacts = Object.values(contactsBook) contacts[0]

наконец, flat () решил эту проблему

contacts = Object.values(contactsBook).flat()

Не могли бы вы помочь объяснить причину?

Ответы [ 2 ]

1 голос
/ 03 апреля 2020

Если бы мне пришлось угадывать, вам нужно добавить в редуктор начальное состояние, которое не является пустым объектом, как пустой массив []. Таким образом, когда компонент сначала рендерится и будет подключен к redux, он будет иметь определенное значение, допустимое для отображения.

edit

Хорошо, так что ваш состояние формы было {[book: string]: string[]}. В этом случае начальное состояние ({}) для редуктора было в порядке, и вам do необходимо извлечь название книги из параметров маршрута. Здесь я обновил функцию mapStateToProps, чтобы также брать собственные реквизиты компонента и выполнять вычисления для возврата contactList в качестве реквизита компонента.

/ edit

Редуктор

const initialState = {};

function contacts(state = initialState, action) {
    switch (action.type) {
        case 'ADD_CONTACT':
            return "....";
        case 'LOAD_CONTACTS':
            return action.contacts;
        default:
            return state
    }
}

Компонент

const { contactList } = this.props;

...

contactList.map(...

...

function mapStateToProps(state, ownProps) {
  const { match: { params: { bookName } } = ownProps;
  return {
    contactList: state.contacts[bookName] || [],
  }
}

Альтернативное решение Защитный паттерн

{
  contacts && contacts.map(
    (contact, index) => (
       <tr key={index}>
         <td>{contact.name}</td>
         <td>{contact.phoneNumber}</td>
       </tr>
  ))
}
0 голосов
/ 03 апреля 2020

Измените свою функцию карты следующим образом:

{contacts["Book1"].map((contact, index) => (
          <tr key={index}>
            <td>{contact.name}</td>
            <td>{contact.phoneNumber}</td>
          </tr>
))}

Код Песочница: https://codesandbox.io/s/react-example-pevdn

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