React + Firebase组件不会在数据更改时重新呈现(删除)

时间:2015-12-01 20:44:26

标签: javascript reactjs firebase

这是渲染/性能问题。

我使用Firebase构建了一个基本的React App。它基本上是有效的,有一个值得注意的异常行为:渲染并不是完全靠它自己发生的。

具体来说,我检索用户所属的组列表,并希望能够添加/删除组,从而触发重新渲染。我使用的是Firebase的.on(' value'),。on(' child_added')和.on(' child_removed')用于绑定对这些事件的引用的函数。

添加和删除组工作,但组列表消失(特别是在删除时注意到),我必须单击按钮(字面意思,UI中的任何按钮)将其恢复(它会立即弹出,基于用户操作的所有正确数据)。

所以 - 我在某个地方明显遗漏了一些东西,虽然我已经测试了各种修复程序并且尚未能够理解这个问题。组件是:

主要管理组件:

var React = require('react'),
    groupRef = new Firebase('http://my-url/groups'), //list of groups
    userRef = new Firebase('http://my-url/users'), //list of users
    groupListArray = [];

var AdminContainer = React.createClass({
    mixins: [ReactFireMixin],

    getInitialState: function() {
        return {
            groups: []
        }
    },
    buildGroupList: function (dataSnapshot) {
        groupListArray = [];
        var groupList = dataSnapshot.val();
        /* The group ids are saved as children in the db
         * under users/$userid/groups to reflect which groups a user can
         * access - here I get the group ids and then iterate over the 
         * actual groups to get their names and other associated data under
         * groups/<misc info>
         */
        for (var key in groupList) {
            if (groupList.hasOwnProperty(key)) {
                groupRef.child(key).once('value', function(snapShot2) {
                    groupListArray.push(snapShot2);
                });
            }
        }
        this.setState({
            groups: groupListArray
        });
    },
    componentWillMount: function() {
        userRef.child(auth.uid).child('groups').on('value', this.buildGroupList);
        userRef.child(auth.uid).child('groups').on('child_removed', this.buildGroupList);
        userRef.child(auth.uid).child('groups').on('child_added', this.buildGroupList);
    },
    handleRemoveGroup: function(groupKey){
        userRef.child(auth.uid).child('groups').child(groupKey).remove(); 
    },
    render: function() {
        <div id="groupAdminDiv">
            <table id="groupAdminTable">
                <thead>
                    <tr>
                         <th>Group Name</th>
                         <th>Action</th>
                    </tr>
                </thead>
                <GroupList groups={this.state.groups} remove={this.handleRemoveGroup} />
            </table>
        </div>
    }
});

module.exports = AdminContainer;

然后是GroupList组件:

var React = require('react');

var GroupList = React.createClass({
    render: function() {
        var listGroups = this.props.groups.map((group, index) => {
            if (group != null) {
                return (
                    <tr key={index} className="u-full-width">
                        <td>
                            {group.val().group_name}
                        </td>
                        <td>
                            <button className="button" onClick={this.props.remove.bind(null, group.key())}>Remove</button>
                        </td>
                    </tr>
                )
            } else {
                return (
                    <tr>
                        <td>You have not added any Groups.</td>
                    </tr>
                )
            }
        });
        return (
            <tbody>
                {listGroups}
            </tbody>
        )
    }
});

module.exports = GroupList;

任何帮助非常感谢!!

2 个答案:

答案 0 :(得分:2)

您似乎已经了解了自己的需求。在componentWillMount方法中,您注册了各种userRef个活动。您只需使用相同的回调注册groupRef事件。每当调用组件setState方法时,React重新呈现,您在buildGroupList内执行此操作。您只需在buildGroupList更新后致电groupRef

componentWillMount: function() {
        var events = ['value', 'child_removed', 'child_added'];
        var refs = [groupRef, userRef.child(auth.uid).child('groups')];
        var callback = this.buildGroupList;
        refs.forEach(function(ref) {
            events.forEach(function(e) {
                ref.on(e, callback);
            });
        });
    },

答案 1 :(得分:1)

我认为这是由使用.once()引起的。根据Firebase的文档,.once()用于查询数据库位置,而不附加持久的侦听器,例如.on('value', callBack)。但是,当我更改我的代码中的实例时,我正在调用.once()来使用.on()(即使我不想在那里附加一个监听器,而只是简单地检索一次数据),所有不稳定的行为都停止了,我的应用程序更新了this.state和组件,正如我原先预期的那样。

我唯一可以从这次经历中剔除的是.once()无法按照预期/陈述的方式运作,而应该使用.on()(加上适当的.off()引用)。< / p>