Совместное использование события хранилища между дочерними компонентами одного уровня иерархии - PullRequest
0 голосов
/ 01 июля 2018

Я занимаюсь разработкой простого приложения React JS для целей обучения. Я только начал изучать React JS несколько дней назад. Теперь у меня проблема с Flux Store. Мне нужно поделиться событием изменения между двумя дочерними компонентами на одном иерархическом уровне.

У меня есть родительский компонент, который называется TodoComponent со следующим определением

//Create
class TodoComponent extends React.Component{
    constructor(props){
        super(props)

    }


    render(){

        return (
            <div>
                <div>
                <ListComponent />
                </div>
                <AddItemComponent />
            </div>
        )
    }
}

Он имеет два дочерних компонента: ListComponent и AddItemComponent. Более того, у меня есть магазин с этим определением.

import { EventEmitter } from 'events';

class DataStore extends EventEmitter{

    constructor()
    {
        super();
        this.todos = [
            "Eat",
            "Sleep",
            "Die",
            "Shower"
        ];
    }

    getAll(){
        return this.todos;
    }

    addItem(newItem)
    {
        this.todos.push(newItem);
        this.emit("change")
    }

}

const dataStore = new DataStore;

export default dataStore;

Имеет функцию добавления нового элемента в массив и функцию извлечения массива.

Это ListComponent, который отображает массив элементов из хранилища потоков DataStore.

import React from 'react';
import TodoItem from './TodoItem';
import DataStore from './data.store';

class ListComponent extends React.Component{
    constructor(props)
    {
        super(props)
        this.state = { todos : DataStore.getAll() };
    }

    componentWillMount(){
        DataStore.on('change', () => {
            //do somethif
            this.state = { todos : DataStore.getAll() };
        })
    }

    render()
    {
        var deleteItem = (item) => {
            this.deleteItem(item);
        }
        var editItem = (item) => {
            this.editItem(item);
        }

        var addItem = (newItem) => {
            this.addItem(newItem);
        }
        var todos = this.state.todos.map((item, index) => {
            return (
                <TodoItem item={item} addItem={addItem.bind(this)} deleteItem={deleteItem} editItem={editItem} />
            )
        });

        return (
            <ul>
                {todos}
            </ul>
        )
    }

    deleteItem(item)
    {
        this.setState({ todos: this.state.todos.filter((listItem, index) => {
            return listItem !== item; 
        }) });
    }

    editItem(item)
    {
        alert(item)
    }

    addItem(newItem)
    {
        DataStore.addItem(newItem);
    }
}

module.exports = ListComponent;

Обновляет элементы в событии изменения хранилища хранилища данных. Но я не вызываю функцию addItem в ListComponent. Я называю это в AddItemComponent. Это определение AddItemComponent.

import React from 'react';
import DataStore from './data.store';

class AddItemComponent extends React.Component{
    constructor(props)
    {
        super(props)

    }

    render()
    {
        return (
            <form id="form-todo" onSubmit={this.addItem.bind(this)} action="post">
                <input type='text' ref="newItem" />
                <button>ADD</button>
            </form>
        );
    }

    addItem(e)
    {
        e.preventDefault();
        DataStore.addItem(this.refs.newItem.value);
    }
}

module.exports = AddItemComponent;  

Но когда я запускаю функцию addItem в AddItemComponent, событие изменения DataStore в ListComponent не запускается. Следовательно, как я могу синхронизировать событие изменения Flux Store между двумя компонентами, существующими на одном иерархическом уровне?

Решение, которое я могу придумать, - это иметь DataStore в TodoComponent (родительский компонент) и отправлять данные и функции в качестве реквизитов дочернему компоненту. Я думаю, что код станет немного грязным в этом смысле. Это единственное решение для этого?

1 Ответ

0 голосов
/ 02 июля 2018

Добро пожаловать в Реакт! Я воссоздал ваш пример, и ваше событие «change» запускается в ListComponent, но для обновления состояния в компоненте вы должны использовать this.setState(changes) вместо this.state = {changes}. Используйте this.state = {} только в конструкторе, чтобы установить начальное состояние. Метод setState правильно проходит через жизненный цикл React и вызывает повторную визуализацию компонента с использованием нового состояния. Существует официальное руководство по состоянию и жизненным циклам React здесь .

...