简体   繁体   中英

Handling multiple instances of the same component in Flux

Take eg the Flux TodoMVC and suppose I want to have two Todo-Apps next to each other.

class TwoTodos extends React.Component {
  render () {
    return (
      <div>
        <TodoApp />
        <TodoApp />
      </div>
    );
  }
}

Now, when you run this example you will notice that both Todo-lists will be synchronized as both emit and listen to the same actions.

What is the canonical way to prevent this?

I just solved this issue. It took me a couple of days to figure it out.

In general, you should make your action and store to be classes, instead of normal objects that can be shared among Todo components. And then create an instance of the action class and store class in every Todo Component.

To avoid components affect each other, you need to encapsulate the public variables that can be shared by different component instances, like _todos in the TodoStore.js, into your store class.

Then you need to wrap what is rendered in the app.js into a class, and create instances of this class before it is used.

I'll put the key changes in the code below.

TodoActions.js:

var Actions = function(){
    //if you have any shared variables, just define them here, instead of outside of the class 

    this.getAction = function(){
        return TodoActions;
    } 
    var TodoActions = {...};
    ...
}
module.exports = Actions;

TodoStore.js:

//private functions
function create(text, todos){...}
function update(id, updates, todos){...}

var Store = function(){
    var _todos = {};
    this.getStore = function(){
        return TodoStore;
    }   

    var TodoStore = assign({}, EventEmitter.prototype, {...});
};
module.exports = Store;

TodoApp.react.js:

var TodoApp = React.createClass({
    Store: function(){},
    Actions: function(){},
    componentWillMount: function(){
        var store = require('path/to/TodoStore.js');
        var storeInstance = new store();
        this.Store = storeInstance.getStore();  

        var action = require('path/to/TodoActions.js');
        var actionInstance = new action();
        this.Store = actionInstance .getAction();  

        this.Store.addChangeListener(...);
    }
    //If you need to call methods in Actions, just call this.Actions.<method_name>
});    
module.exports = TodoApp;

app.js:

var TodoApp = require('./components/TodoApp.react');
window.Todo = function(){
    var todo = null; //In case you need to get/set the component
    this.use = function(elementId){
        todo = ReactDom.render(
            <TodoApp />,
            document.getElementById(elementId)
        )
    }
};

index.html:

<section id="todoapp1"></section>
<section id="todoapp2"></section>
<script>
    var todo1 = new Todo();
    var todo2 = new Todo();
    todo1.use('todoapp1');
    todo2.use('todoapp2');
</script>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM