vendredi 27 novembre 2015

How to fast render >10000 items using React + Flux?

I would like to ask what is the correct way to fast render > 10000 items in React.

Suppose I want to make a checkboxList which contain over dynamic 10000 checkbox items.

I make a store which contain all the items and it will be used as state of checkbox list.

When I click on any checkbox item, it will update the corresponding item by action and so the store is changed.

Since store is changed so it trigger the checkbox list update.

The checkbox list update its state and render again.

The problem here is if I click on any checkbox item, I have to wait > 3 seconds to see the checkbox is ticked. I don't expect this as only 1 checkbox item need to be re-rendered.

I try to find the root cause. The most time-consuming part is inside the checkbox list render method, related to .map which create the Checkbox component to form componentList.. But actually only 1 checkbox have to re-render.

The following is my codes. I use ReFlux for the flux architecture.

CheckboxListStore

The Store store all the checkbox item as map. (name as key, state (true/false) as value)

const Reflux = require('reflux');
const Immutable = require('immutable');
const checkboxListAction = require('./CheckboxListAction');

let storage = Immutable.OrderedMap();
const CheckboxListStore = Reflux.createStore({
        listenables: checkboxListAction,
        onCreate: function (name) {
                if (!storage.has(name)) {
                        storage = storage.set(name, false);
                        this.trigger(storage);
                }
        },
        onCheck: function (name) {
                if (storage.has(name)) {
                        storage = storage.set(name, true);
                        this.trigger(storage);
                }
        },
        onUncheck: function (name) {
                if (storage.has(name)) {
                        storage = storage.set(name, false);
                        this.trigger(storage);
                }
        },
        getStorage: function () {
                return storage;
        }
});

module.exports = CheckboxListStore;

CheckboxListAction

The action, create, check and uncheck any checkbox item with name provided.

const Reflux = require('reflux');
const CheckboxListAction = Reflux.createActions([
        'create',
        'check',
        'uncheck'
]);
module.exports = CheckboxListAction;

CheckboxList

const React = require('react');
const Reflux = require('reflux');
const $ = require('jquery');
const CheckboxItem = require('./CheckboxItem');
const checkboxListAction = require('./CheckboxListAction');
const checkboxListStore = require('./CheckboxListStore');
const CheckboxList = React.createClass({
        mixins: [Reflux.listenTo(checkboxListStore, 'onStoreChange')],
        getInitialState: function () {
                return {
                        storage: checkboxListStore.getStorage()
                };
        },
        render: function () {
                const {storage} = this.state;
                const LiComponents = storage.map((state, name) => {
                        return (
                                <li key = {name}>
                                        <CheckboxItem name = {name} />
                                </li>
                        );
                }).toArray();
                return (
                        <div className = 'checkbox-list'>
                                <div>
                                        CheckBox List
                                </div>
                                <ul>
                                        {LiComponents}
                                </ul>
                        </div>
                );
        },
        onStoreChange: function (storage) {
                this.setState({storage: storage});
        }
});

module.exports = CheckboxList;

CheckboxItem Inside onChange callback, I call the action to update the item.

const React = require('react');
const Reflux = require('reflux');
const $ = require('jquery');
const checkboxListAction = require('./CheckboxListAction');
const checkboxListStore = require('./CheckboxListStore');

const CheckboxItem = React.createClass({
        mixins: [Reflux.listenTo(checkboxListStore, 'onStoreChange')],
        propTypes: {
                name: React.PropTypes.string.isRequired
        },
        getInitialState: function () {
                const {name} = this.props;
                return {
                        checked: checkboxListStore.getStorage().get(name)
                };
        },
        onStoreChange: function (storage) {
                const {name} = this.props;
                this.setState({
                        checked: storage.get(name)
                });
        },
        render: function () {
                const {name} = this.props;
                const {checked} = this.state;
                return (
                        <div className = 'checkbox' style = {{background: checked ? 'green' : 'white'}} >
                                <span>{name}</span>
                                <input ref = 'checkboxElement' type = 'checkbox'
                                        onChange = {this.handleChange}
                                        checked = {checked}/>
                        </div>
                );
        },
        handleChange: function () {
                const {name} = this.props;
                const checked = $(this.refs.checkboxElement).is(':checked');
                if (checked) {
                        checkboxListAction.check(name);
                } else {
                        checkboxListAction.uncheck(name);
                }
        }
});

module.exports = CheckboxItem;



Aucun commentaire:

Enregistrer un commentaire