Как отладить проблему action.type с помощью response-redux, одиночного редуктора с одним действием, но он не распознает тип - PullRequest
0 голосов
/ 10 апреля 2019

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

if(action.type === ADD_ITEM) затем возврат (код редуктора)

эта функция редуктора вызывается в моем магазине. Когда я тестировал свое приложение, состояние не обновлялось, и, добавив некоторые console.logs, чтобы увидеть, в чем проблема, я понял, что код редуктора не вызывается, потому что action.type === ADD_ITEM возвращается как false.

Я попытался записать в консоль action.type, но я только что получил значение по умолчанию {type: @@redux/INITp.m.x.p.a.c}, которое мало что говорит мне о том, почему он не читает action.type как ADD_ITEM.

Кстати: тип действия передается в import { ADD_ITEM } from "../constants/action-types";, а action-types содержит это export const ADD_ITEM = "ADD_ITEM";, потому что я предпочитаю использовать константы для строк для этого.

Я знаю, что action.type не вызывается как "ADD_ITEM", но я не знаю почему, и у меня не хватает мест для проверки. Я рассмотрел другие вопросы, подобные этому, по переполнению стека, но все они включали использование switch для нескольких типов действий, или использование комбинированных редукторов, или наличие action.type как неопределенного. У меня есть только одно действие и один редуктор, и action.type не возвращается как неопределенное, а просто не возвращается как тип действия, который я настроил для вызова функции редуктора. Кроме того, это мой первый раз, когда я использую редукс, поэтому, пожалуйста, будьте добры.

Действие:

import { ADD_ITEM } from "../constants/action-types";

export function addArticle(payload){
    return { type: ADD_ITEM, payload };
};

action-types.js: export const ADD_ITEM = "ADD_ITEM";

редуктор:

import { ADD_ITEM } from "../constants/action-types";

const initialState = {
    articles: []
};

function rootReducer(state = initialState, action){
    if(action.type === ADD_ITEM){
        console.log("yes");
        return Object.assign({}, state, {
            articles: state.articles.concat(action.payload)
        });
    }
    console.log("no");
    return state;
};

export default rootReducer; 

магазин:


import { createStore } from "redux";
import rootReducer from '../reducers/index';

const store = createStore(rootReducer);

export default store;

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

import React, { Component } from "react";
import { connect } from "react-redux";
import uuidv1 from "uuid";
import { addArticle } from "../actions/index";

function mapDispatchToProps(dispatch){
    return {
        addArticle: article => dispatch(addArticle(article))
    };
}

class ConnectedForm extends Component {
    constructor() {
        super();

        this.state = {
            title: ""
        };

        this.handleChange = this.handleChange.bind(this);
        this.handleSubmit = this.handleChange.bind(this);
    }

    handleChange(event) {
        this.setState({ [event.target.id]: event.target.value });
    }

    handleSubmit(event) {
        event.preventDefault();
        const { title } = this.state;
        const id = uuidv1();
        this.props.addArticle({ title, id });
        this.setState({ title: "" });
    }

    render() {
        const { title } = this.state;

        return (
            <form onSubmit={this.handleSubmit}>
                <div className="form-group">
                <label htmlFor="title">Title</label>
                <input
                    type="text"
                    className="form-control"
                    id="title"
                    value={title}
                    onChange={this.handleChange}
                />
                </div>
                <button type="submit" className="btn btn-success">
                SAVE
                </button>
            </form>
        );
    }
}

const Form = connect(null, mapDispatchToProps)(ConnectedForm);

export default Form;

список, в котором должны отображаться добавленные статьи:

import React from "react";
import { connect } from "react-redux";

const mapStateToProps = state => {
    return { articles: state.articles };
};

const ConnectedList = ({ articles }) => (
    <ul className="list-group list-group-flush">
    {articles.map(el => (
        <li className="list-group-item" key={el.id}>
        {el.title}
        </li>
    ))}
    </ul>
);

const List = connect(mapStateToProps)(ConnectedList);

export default List;

index.js, где я устанавливаю провайдера:


import React from 'react';
import { render } from 'react-dom';
import { Provider } from 'react-redux';
import store from "./store/index";
import App from './components/App.jsx';

render(
<Provider store={store}>
<App />
</Provider>
, document.getElementById('root')
);

приложение, где оно собрано вместе:

import React, { Component } from 'react';
import List from "./List";
import Form from "./Form";

class App extends Component {
  render() {
    return (
      <div className="row mt-5">
        <div className="col-md-4 offset-md-1">
        <h2>Article List</h2>
        <List />
        </div> 
        <div className="col-md-4 offset-md-1">
        <h2>Add a new article</h2>
        <Form />
        </div>
      </div>
    );
  }
}

export default App;

Я ожидаю, что когда я введу заголовок и отправлю форму, она должна вызвать dispatch с этой новой «статьей», добавить ее в состояние и затем распечатать как часть компонента списка.

Но та часть редуктора, которая фактически добавляет новый вход в начальное состояние, не работает, потому что action.type === ADD_ITEM возвращается как ложное.

Примечание: когда я запускаю это только в консоли из файла testing.js со следующим:

import store from "../js/store/index";
import { addArticle } from "../js/actions/index";
window.store = store;
window.addArticle = addArticle;

Я могу запустить store.getState () в консоли, и он вернет пустой массив, затем я могу запустить что-то вроде

store.dispatch( addArticle({ title: 'What is happening?', id: 1 }) )

и он добавит это в массив.

Так что эта логика работает, но я думаю, потому что когда я запускаю ее с компонентом формы и не вызываю напрямую store.dispatch, он опирается на этот оператор action.type === ADD_ITEM, поэтому никакая другая логика на самом деле не вызывается.

Я просто понятия не имею, почему action.type не читается как ADD_ITEM, поскольку в моем файле action.js я определяю функцию addArticle с типом ADD_ITEM

любая помощь будет оценена

РЕДАКТИРОВАТЬ:

Я забыл упомянуть, в редукторе, если я console.log(addArticle()) возвращает это

{type: "ADD_ARTICLE", payload: undefined}
payload: undefined
type: "ADD_ARTICLE"
__proto__: Object

, поэтому addArticle () имеет тип "ADD_ARTICLE", но действие, которое я передаю rootReducer, не имеет ..

1 Ответ

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

Оказывается, когда я связывал свои обработчики, у меня было

 this.handleChange = this.handleChange.bind(this);
 this.handleSubmit = this.handleChange.bind(this);

вместо

 this.handleChange = this.handleChange.bind(this);
 this.handleSubmit = this.handleSubmit.bind(this);

, поэтому handleSubmit не вызывался.У меня было чувство, что это будет что-то простое

...