2017-10-06 10 views
0

J'apprends Flux dans ReactJS. J'ai écrit un code simple dans ReactJS en utilisant le pattern Flux. Dans ce code, certains enregistrements sont affichés et il est possible d'ajouter un nouvel enregistrement. Le problème est que lorsque je déclenche un événement, c'est-à-dire lorsque je clique sur le bouton d'ajout, la fonction de rappel n'est pas appelée depuis this.on(CHANGE_EVENT, callback); et, par conséquent, le nouvel enregistrement n'est pas affiché à l'écran. Par conséquent s'il vous plaît dites, pourquoi cette fonction callback n'est pas appelée? Et comment résoudre ce problème?La fonction de rappel n'est pas appelée sur le feu d'événement

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; 

Répondre

0

Voici comment je mettre en place un magasin flux - les points clés sont les suivants:

  • enregistrer le rappel de répartition dans le constructeur

  • Il est plus facile d'avoir une seule constante CHANGE_EVENT et de la cacher à l'intérieur du magasin.

  • En règle générale, vous ne voulez que vos magasins aient qu'une seule instance. Donc, quand vous l'exportez, vous voulez export default new Store(). De cette façon, tous les composants seront en mesure d'utiliser le même magasin.

Magasin

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(); 

-

Dans la vue, vous devez lier vos auditeurs componentDidMount et souvenez-vous de retirer les auditeurs componentWillUnmount.

Voir

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() 
    }); 
    } 
}