首页 > 解决方案 > 在我的 Todo ReactApp 中,我使用的是通量。使用 useEffect 我添加了一个监听器,但是当 Todostore 更新页面时不会重新呈现。为什么不?

问题描述

下面是我的 TodoList 组件。使用 useEffect 我在组件首次安装时添加一个侦听器,并在组件安装后将其删除。但是当我添加一个做页面时不会重新渲染/更新。当我打电话给商店时,我看到商店确实使用新的 todoitem 进行了更新。我究竟做错了什么?

Todolist 组件:

import React, { useState, useEffect } from 'react';
import todoStore from '../Store/TodoStore';
import TodoItem from './TodoItem';
import * as TodoActions from '../Store/TodoActions';

function TodoList() {
    const [todos, setTodos] = useState(todoStore.getAll());

    const onChange = () => {
        setTodos(todoStore.getAll());
    };

    useEffect(() => {
        todoStore.on('change', onChange);
        console.log('count: ', todoStore.listenerCount('change'));
        return () => todoStore.removeListener('change', onChange);
    }, []);

    const todoComponents = todos.map((todo) => {
        return <TodoItem key={todo.id} text={todo.text} complete={todo.complete} />;
    });

    const createTodo = () => {
        TodoActions.createTodo(Date.now());
    };

    return (
        <div>
            <h1>Todo List</h1>
            {todoComponents}
            <button onClick={createTodo}>Create!</button>
        </div>
    );
}

export default TodoList;

待办事项商店:

import { EventEmitter } from 'events';
import Dispatcher from './TodoDispatcher';

class TodoStore extends EventEmitter {
    constructor() {
        super();
        this.todos = [
            { id: 123, text: 'shopping', complete: false },
            { id: 412, text: 'laundrey', complete: false },
        ];
    }
    getAll() {
        return this.todos;
    }

    createTodo(text) {
        const id = Date.now();
        this.todos.push({ id, text, complete: false });
        this.emit('change');
    }

    handleActions(action) {
        switch (action.type) {
            case 'CREATE_TODO':
                this.createTodo(action.text);
                break;
            case 'RECEIVE_TODOS':
                this.todos = action.todos;
                this.emit('change');
                break;
            default:
                break;
        }
    }
}

const todoStore = new TodoStore();
Dispatcher.register(todoStore.handleActions.bind(todoStore));
window.todoStore = todoStore;
window.Dispatcher = Dispatcher;
export default todoStore;

创建动作:

import Dispatcher from './TodoDispatcher';

export function createTodo(text) {
    Dispatcher.dispatch({
        type: 'CREATE_TODO',
        text,
    });
}

标签: reactjsstoreflux

解决方案


React doesn't rerender the page because it did not see that the store updated because the onChange had a reference to the previous state of the store.

I changed the onChange function so that a new array is created every time the store updates. something like this:

    const onChange = () => {
        setTodos([...todoStore.todos]);
    };


推荐阅读