React + Firebase组件不会在数据更改时重新呈现(移除) [英] React + Firebase Component does not re-render on data change (remove)

查看:124
本文介绍了React + Firebase组件不会在数据更改时重新呈现(移除)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是一个渲染/性能问题。

我使用Firebase构建了一个基本的React应用程序。它基本上工作,有一个显着的异常行为:渲染不会完全发生在它自己。

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

<添加和删​​除组的作品,但是组列表消失(特别是在删除时注意到),我必须点击一个按钮(字面上,在用户界面中的任何按钮)将其恢复(它立即弹出,所有基于用户操作的正确数据)。所以 - 我明显错过了某个地方的东西,虽然我一直在测试各种修补程序,但还没有能够理解这个问题。组件是:

主要管理组件:

  var React = require ('react'),
groupRef = new Firebase('http:// my-url / groups'),//群组列表
userRef = new Firebase('http:// my-url / users'),//用户列表
groupListArray = [];

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

getInitialState:function(){
return {
groups:[]
}
},
buildGroupList:function(dataSnapshot){
groupListArray = [];
var groupList = dataSnapshot.val();
/ *组ID被保存为db
*下users / $ userid / groups中的孩子,以反映哪些用户可以
*访问 - 这里我得到组ID,然后迭代
*实际组获得他们的名字和
* groups /< misc info>
* /
下的其他相关数据(groupList中的var键){$ b $ (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>
< th>动作< / th>
< / tr>
< / thead>
< GroupList groups = {this.state.groups} remove = {this.handleRemoveGroup} />
< / table>
< / div>
}
});

module.exports = AdminContainer;

然后GroupList组件:

  var React = require('react'); 
$ b $ 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 =buttononClick = {this.props.remove。删除< / button>
< / td>
< / tr>

} else {
$(
< tr>
< td>您还没有添加任何群组< / td>
< / tr>

}
});
返回n(
< tbody>
{listGroups}
< / tbody>

}
});

module.exports = GroupList;

非常感谢任何帮助! 。根据Firebase的文档, .once()用于查询数据库位置,而不需要附加诸如 .on('value',callBack )。然而,当我改变了我调用 .once()的代码中的实例来使用 .on() (即使我不想附加一个侦听器,而只是简单地检索一次数据),所有的错误行为停止,我的应用程序更新 this.state 和组件我原本预料到了。



我从这个体验中唯一可以拿走的是 .once()并且应该使用 .on()(加上适当的 .off()引用)。


This is a rendering / performance problem.

I've built a basic React App using Firebase. It basically works, with one notable anomalous behavior: rendering doesn't occur entirely on its own.

Specifically, I retrieve a list of groups to which a user belongs, and want to be able to add/remove groups, triggering a re-render. I'm using Firebase's .on('value'), .on('child_added'), and .on('child_removed') functions to bind references to these events.

Adding and removing groups works, however the group list disappears (especially noticed on remove), and I have to to click on a button (literally, any button in the UI) to bring it back (it pops up immediately, with all the correct data based on user action).

So - I'm clearly missing something somewhere, although I've been testing various fixes and have yet to be able to understand the issue. Components are:

Main Admin Component:

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;

Then the GroupList Component:

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;

Any help much appreciated!!

解决方案

I believe this was caused by use of .once(). As per Firebase's documentation, .once() is used to query a database location without attaching an enduring listener such as .on('value', callBack). However, when I changed the instances in my code where I was calling .once() to use .on() (even though I didn't want to attach a listener there but instead simply retrieve data one time), all the erratic behavior stopped and my app updated this.state and components as I had originally expected it to.

The only thing I can take away from this experience is that .once() does not function as intended / stated and that .on() (plus appropriate .off() references) should be used instead.

这篇关于React + Firebase组件不会在数据更改时重新呈现(移除)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆