Как исправить «TypeError: this.props.messages.map не является функцией» в response-redux - PullRequest
1 голос
/ 03 апреля 2019

Я пытаюсь передать реквизиты моему компоненту через mapDispatchToProps (). Однако я столкнулся с этой проблемой

TypeError: this.props.messages.map is not a function
DisplayMessages.render
C:/Users/User/Desktop/Project/first-react-redux/src/DisplayMessages.js:38
  35 |             <h2>Type in a new message</h2>
  36 |             <input value={input} onChange={this.handleChange} />
  37 |             <button onClick={this.submitMessage}>Submit</button>
> 38 |             <ul>{this.props.messages.map((message, index) => <li key={index}>{message}</li>)}</ul>
     | ^  39 |         </div >
  40 |     )
  41 | }

Моя страница может отображаться, если я раскомментирую строку 38. Однако после нажатия кнопки я получаю это сообщение об ошибке:

TypeError: Object(...) is not a function
submitNewMessage
C:/Users/User/Desktop/Project/first-react-redux/src/DisplayMessagesContainer.js:18
  16 |     return {
  17 |         submitNewMessage: (newMessage) => {
> 18 |             dispatch(addMessage(newMessage))
  19 |         }
  20 |     }
  21 | };

Я новичок в React-redux и не уверен, что пошло не так. Пример, над которым я сейчас работаю, взят из freecodecamp, и я проверил эти коды в редакторе кода и выполнил задание (за исключением того времени, когда я делаю это на своем компьютере и структурирую свое собственное дерево файлов).

Вот так выглядит мой компонент:

import React from 'react';

export default class DisplayMessages extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            input: '',
        }
    }

    handleChange = (event) => {
        this.setState({
            input: event.target.value
        })
    }

    submitMessage = () => {
        this.props.submitNewMessage(this.state.input)
        this.setState({
            input: '',
       })
    }


    render() {
        const { input} = this.state
        return (
            <div>
                <h2>Type in a new message</h2>
                <input value={input} onChange={this.handleChange} />
                <button onClick={this.submitMessage}>Submit</button>
                <ul>{this.props.messages.map((message, index) => <li key={index}>{message}</li>)}</ul>
            </div >
        )
    }
}

А это мой контейнер:

import DisplayMessages from './DisplayMessages';
import { connect } from 'react-redux';
import addMessage from './redux/actions'

mapStateToProps
const mapStateToProps = (state) => {
    return { messages: state }
};

const mapDispatchToProps = (dispatch) => {
    return {
        submitNewMessage: (message) => {
            dispatch(addMessage(message))
        }
    }
};

const DisplayMessagesContainer = connect(mapStateToProps, mapDispatchToProps)(DisplayMessages)

export default DisplayMessagesContainer

Мой редуктор.js:

import { combineReducers } from 'redux';
import types from './types';

const defaultState = [];
const messageReducer = (state = defaultState, action) => {
    switch (action.type) {
        case types.ADD:
            return [...state].concat(action.message)
            break;
        default:
            return state
    }
}

const rootReducer = combineReducers({
    message: messageReducer
});

export default rootReducer;

Мои action.js для создателей экшена:

import types from './types.js';

const addMessage = (message) => {
    return {
        type: types.ADD,
        message: message
    }
}

export default {
    addMessage,
}

И мой type.js:

const ADD = "ADD"

export default {
    ADD,
}

Так что же на самом деле пошло не так с моим кодом?

Любая помощь по этому вопросу очень ценится.

Спасибо


EDIT: Я подтвердил, что this.props.messages - это объект, а не массив. Но мой следующий вопрос: почему я смог отобразить объект в редакторе кода в freecodecamp, но не сейчас? И как мне исправить эту проблему?

Ответы [ 3 ]

0 голосов
/ 03 апреля 2019

1) Вы должны добавить реквизиты по умолчанию, такие как DisplayMessages.defaultProps = {messages: []}

2) Проверить тип сообщений в mapstatetoprops, массив это или объект.3) карта работает только на массиве

0 голосов
/ 03 апреля 2019

В вашем редукторе вы определили

const rootReducer = combineReducers({
    message: messageReducer
});

Вы должны установить mapStateToProps как это?

//mapStateToProps
const mapStateToProps = (state) => {
    return { messages: state.message }
};

Поскольку вы не хотите задавать все состояние как сообщения (а состояние является объектом), вы хотите установить сообщения как state.message (message => name from reducer).

Редактировать Если честно, я никогда не пользовался таким mapDispatchToProps, я просто импортирую действия и передаю их как второй параметр для подключения (...) actions - ваш экспорт по умолчанию, и он содержит функцию addMessage, эту функцию и все остальное будет помещено в реквизит, когда вы передадите его таким образом. и если вы делаете именной экспорт

//named export example 
export const addMessage()...
//import would be like
import {addMessage} from './redux/actions'
//passing to connect would be like 
export default connect(mapStateToProps, {addMessage});

и использование будет таким же, как в примере.

например

import actions from './redux/actions'

// inside DisplayMessages  i use action like
 submitMessage = () => {
        this.props.addMessage(this.state.input)
        this.setState({
            input: '',
       })
    }

export default connect(mapStateToProps, actions)(DisplayMessages)
0 голосов
/ 03 апреля 2019

@ chubbybunny map function работает только с массивами.проверьте, является ли this.props.messages массивом.

...