【问题标题】:callback function is not being called on event fire事件触发时未调用回调函数
【发布时间】:2018-03-17 21:06:22
【问题描述】:

我正在学习 ReactJS 中的 Flux。我使用 Flux 模式在 ReactJS 中编写了一个简单的代码。在此代码中,正在显示一些记录,并且可以选择添加新记录。问题是当我触发一个事件时,即当我单击添加按钮时,不会从this.on(CHANGE_EVENT, callback); 调用回调函数,因此,新记录不会显示在屏幕上。因此请告诉我,为什么这个callback 函数没有被调用?以及如何解决这个问题?

Store.js

import React from 'react';
import Dispatcher from './Dispatcher.js';
import { EventEmitter } from "events";

class Store extends EventEmitter {

    constructor() {
        super();
        this.records = [
            {
                id: 1,
                name: 'First Record'
            },
            {
                id: 2,
                name: 'Second Record'
            },
            {
                id: 3,
                name: 'Third Record'
            },
            {
                id: 4,
                name: 'Fourth Record'
            },
            {
                id: 5,
                name: 'Fifth Record'
            }
        ]
    };

    createRecord(name, id) {
        this.records.push({
            id: id,
            name: name
        });
        this.emit("change");
    }

    addChangeListener(CHANGE_EVENT, callback) {
        this.on(CHANGE_EVENT, callback);
    }

    handleActions(action) {
        switch(action.type) {
            case "ADD_RECORD": {
                this.createRecord(action.name, action.id);
                break;
            }
        }
    }

    getRecords() {
        return this.records;
    }
};

const recordsStore = new Store();
Dispatcher.register(recordsStore.handleActions.bind(recordsStore));

export default Store;

View.jsx

import React from 'react';
import Store from './Store.js';
import {addRecord} from "./Action.js";


class View extends React.Component {
    constructor() {
        super();
        this.Store = new Store();
        this.state = {records: this.Store.getRecords()};
    }

    render() {
        return (
            <div className="container" style={{marginTop:'25px'}}>
                <ul className="list-group">
                    <li style={{backgroundColor:'#696969', color:'#f5f5f5', textAlign:'center', padding:'5px', fontSize:'16px', borderRadius:'5px 5px 0px 0px'}}><b>Records</b></li>
                    {this.state.records.map((eachRecord,index) =>
                        <ListItem key={index} singleRecord={eachRecord} />
                    )}
                </ul>
                <input type="text" ref="input"/>
                <button  onClick={()=>addRecord(this.refs.input.value)}>Add</button>
            </div>
        );
    }

    componentWillMount() {
        this.Store.addChangeListener("change", this.updateStore);
    }

    updateStore() {
        this.setState({
            records: this.Store.getRecords()
        });
    }
}

class ListItem extends React.Component {
    render() {
        return (
            <li className="list-group-item" style={{cursor:'pointer'}}>
                <b>{this.props.singleRecord.name}</b>
                <button style={{float:'right'}}>Delete</button>
            </li>
        );
    }
}

export default View;

【问题讨论】:

    标签: reactjs flux


    【解决方案1】:

    这就是我建立助焊剂商店的方式——关键点是:

    • 在构造函数中注册调度回调

    • 拥有一个 CHANGE_EVENT 常量并将其隐藏在 store 中更容易。

    • 通常您会希望您的商店只有一个实例。所以当你导出它时,你会export default new Store()。这样所有组件都可以使用同一个商店。

    商店

    const CHANGE_EVENT = 'change';
    
    class Store extends EventEmitter {
      constructor() {
        super();
        Dispatcher.register(this.handleActions.bind(this));
      }
    
      createRecord(name, id) {
        // code..
        this.emitChange();
      }
    
      emitChange() {
        this.emit(CHANGE_EVENT);
      }
    
      addChangeListener(callback) {
        this.on(CHANGE_EVENT, callback);
      }
    
      removeChangeListener(callback) {
        this.removeListener(CHANGE_EVENT, callback);
      }
    
      handleActions(action) {
        switch (action.type) {
          case 'ADD_RECORD': {
            this.createRecord(action.name, action.id);
            break;
          }
        }
      }
    
      getRecords() {
        return this.records;
      }
    }
    
    export default new Store();
    

    --

    在视图中,你应该在componentDidMount中绑定你的监听器,并记得移除componentWillUnmount中的监听器。

    查看

    import Store from './Store';
    
    class View extends React.Component {
      constructor() {
        super();
        this.state = {records: Store.getRecords()};
      }
    
      render() {
        // code..
      }
    
      componentDidMount() {
        Store.addChangeListener(this.updateStore);
      }
    
      componentWillUnmount() {
        Store.removeChangeListener(this.updateStore);
      }
    
      // use this syntax to keep context or use .bind in the constructor
      updateStore = () => {
        this.setState({
          records: Store.getRecords()
        });
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-04-09
      • 2012-10-01
      • 2021-06-22
      • 2013-05-31
      • 2012-08-09
      • 2015-07-18
      • 2020-03-04
      • 1970-01-01
      相关资源
      最近更新 更多