首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >将新的服务器数据传递给react.js组件

将新的服务器数据传递给react.js组件
EN

Stack Overflow用户
提问于 2013-12-16 15:13:45
回答 3查看 22.7K关注 0票数 23

我刚接触React.js,正在努力理解一些核心概念来决定我们是否应该将这个库用于我们的应用程序。我的主要问题实际上是处理从服务器获取的模型中的更新。

想象一下,我有一个页面,它应该显示五个不同的模型。我用本文中描述的方式构建了它:http://facebook.github.io/react/blog/2013/11/05/thinking-in-react.html,所以我有“根”组件,所有5个模型都通过了,并使用道具将它们向下延伸到包含这些模型的组件。因此,现在更新了2个模型(我从位于react组件之外的模型代码中获取此事件),并且我需要在UI上反映这一点。做这件事最好的方法是什么?

我在考虑以下几种选择:

  1. 再次使用新数据运行renderComponent,并依赖于DOM diff反应技术。我对此有顾虑,因为我需要对任何微小的数据更改执行此操作。
  2. 为包含此模型的组件调用setState。这样,数据就不再是支柱,而是状态,这(据我所知)不是一种好做法。此外,我看不到任何方法可以在根component.
  3. Having多个renderComponent调用之外获得对子组件的引用,因此通过这种方式,我将能够访问该组件的setProps。但是,我需要做一些模板化工作(使页面上的所有容器都可用),这会扼杀所有的react想法。
  4. 具有一个根组件,该组件包含应用程序中显示给用户的所有可能的模型,并调用setProps来更改模型。我在这里的担忧是,这个组件会变得非常大,并在某个时候变成“意大利面”+从第一点开始的担忧。

提前谢谢你,希望我能把我的问题解释清楚。

EN

回答 3

Stack Overflow用户

发布于 2013-12-17 00:22:35

使用相同的组件但不同的数据再次调用renderComponent等同于调用component.setProps()。因此,要么在最小公分母中保持所有模型的状态,要么在它发生变化时再次调用setProps/renderComponent。

票数 6
EN

Stack Overflow用户

发布于 2013-12-17 04:59:25

如果你将数据作为道具传递给你的子组件,你可以简单地在更高的级别更新它,它将强制渲染到使用相同属性对象的所有组件。考虑这个简单的例子:

代码语言:javascript
复制
var World = React.createClass({
    render: function() {
        return <strong>{this.props.name}</strong>;
    }
});

var Hello = React.createClass({
    clickHandler: function() {
        this.setProps({ name: 'earth' });
    },
    render: function() {
        return (
            <div>
                Hello <World name={this.props.name} />
                <button onClick={this.clickHandler}>Click me</button>
            </div>
        );
    }
});

现在,当用户单击按钮时,您将更改Hello组件上的属性,但由于您将相同的属性(或数据)对象传递给子组件,因此它们将对此做出反应,并相应地更新其阴影DOM。

这就是我想说的:http://jsfiddle.net/xkCKR/

如果你有一个外部数据对象,你可以直接把它传递给顶层组件。请记住,这并不意味着存在双向绑定:

代码语言:javascript
复制
// simple example of a data model
var Data = { name: 'world' };

var World = React.createClass({
    render: function() {
        return <strong>{this.props.data.name}</strong>;
    }
});

var Hello = React.createClass({
    clickHandler: function() {
        this.setProps({
            data: { name: 'earth' }
        });
    },
    render: function() {
        return (
            <div>
                Hello <World data={this.props.data} />
                <button onClick={this.clickHandler}>Click me</button>
            </div>
        );
    }
});

React.renderComponent(<Hello data={Data} />, document.body);

这是因为react使用属性的单向绑定。但是如果你的子组件会更新它的属性,它就不会上升到它的父组件。为此,您将需要ReactLink add-on或使用Backbone提供的发布/订阅接口。

票数 5
EN

Stack Overflow用户

发布于 2015-08-24 15:46:14

目前,我知道至少有三种方法可以将新数据传递给组件:

  1. 重新呈现组件。不要担心这种方法的效率,因为React似乎处理得很好。关于这一点有一些很好的文章:Change And Its Detection In JavaScript FrameworksUpdating with React.render
  2. Use PubSub,允许组件在数据更改时得到通知(在How to communicate between React components帖子中可以找到一些有用的示例)。带有回调的
  3. 绑定(参见下面的三个jsfiddles )

对于第三种选择,我受到了StevenH的回答的启发,并对其进行了一点扩展。请在jsfiddle.net/kb3gN/12002/查看我的实现。

代码语言:javascript
复制
var Data = { value: 1 };

var dataChange = function(callback){
    if(callback){
        callback(Data);
        setInterval(function(){
            Data.value++;
            callback(Data);
        }, 1000);
    }
    return Data;
};

var World = React.createClass({
    render: function() {
        return <strong>{this.props.data.value}</strong>;
    }
});

var Hello = React.createClass({
    getInitialState: function() {
        return {
          data: this.props.dataChange()
        };
    },
    componentDidMount: function() {
        this.props.dataChange(this.updateHandler)
    },
    updateHandler: function(data) {
        this.setState({
          data: data
        });
    },
    render: function() {
        return (
            <div>
                Value: <World data={this.state.data} />
            </div>
        );
    }
});

React.renderComponent(<Hello dataChange={dataChange} />, document.body);

此外,在jsfiddle.net/kb3gN/12007上还有一个扩展版本。

代码语言:javascript
复制
function ListenersService(){
    var listeners = {};
    this.addListener = function(callback){
        var id;
        if(typeof callback === 'function'){
            id = Math.random().toString(36).slice(2);
            listeners[id] = callback;
        }
        return id;
    }
    this.removeListener = function( id){
        if(listeners[id]){
            delete listeners[id];
            return true;
        }
        return false;
    }
    this.notifyListeners = function(data){
        for (var id in listeners) {
          if(listeners.hasOwnProperty(id)){
            listeners[id](data);
          }
        }
    }
}

function DataService(ListenersService){
    var Data = { value: 1 };
    var self = this;

    var listenersService = new ListenersService();
    this.addListener = listenersService.addListener;
    this.removeListener = listenersService.removeListener;
    this.getData = function(){
        return Data;
    }

    setInterval(function(){
        Data.value++;
        listenersService.notifyListeners(Data);
    }, 1000);
}
var dataSevice = new DataService(ListenersService);

var World = React.createClass({
    render: function() {
        return <strong>{this.props.data.value}</strong>;
    }
});

var Hello = React.createClass({
    getInitialState: function() {
        return {
          data: this.props.dataService.getData()
        };
    },
    componentDidMount: function() {
        this.props.dataService.addListener(this.updateHandler)
    },
    updateHandler: function(data) {
        this.setState({
          data: data
        });
    },
    render: function() {
        return (
            <div>
                Value: <World data={this.state.data} />
            </div>
        );
    }
});

React.renderComponent(<Hello dataService={dataSevice} />, document.body);

这种实现并不完全遵循隔离组件的思想(因为Hello组件依赖于DataService应用程序接口),但它可以进一步抽象,并由应用程序开发人员决定其组件将遵循哪些特定于应用程序的约定。例如,请参阅jsfiddle.net/kb3gN/12015 (halloDataStatic对象和halloDataDynamic回调)中第一个和第二个示例的混合

注意:示例中使用的ListenersService遵循观察者模式,在许多情况下,该模式本身的缺点多于优点。但除此之外,我想通过这些示例说明的是,有一种使用回调进行数据绑定的方法

代码语言:javascript
复制
<div id="static"></div>
<div id="dynamic"></div>
<script>

function ListenersService(){
    var listeners = {};
    this.addListener = function(callback){
        var id;
        if(typeof callback === 'function'){
            id = Math.random().toString(36).slice(2);
            listeners[id] = callback;
        }
        return id;
    }
    this.removeListener = function( id){
        if(listeners[id]){
            delete listeners[id];
            return true;
        }
        return false;
    }
    this.notifyListeners = function(data){
        for (var id in listeners) {
          if(listeners.hasOwnProperty(id)){
            listeners[id](data);
          }
        }
    }
}

function DataService(ListenersService){
    var Data = { value: 1 };
    var self = this;

    var listenersService = new ListenersService();
    this.addListener = listenersService.addListener;
    this.removeListener = listenersService.removeListener;
    this.getData = function(){
        return Data;
    }

    setInterval(function(){
        Data.value++;
        listenersService.notifyListeners(Data);
    }, 100);
}
var dataSevice = new DataService(ListenersService);
var halloDataDynamic = function(callback){
    var data = dataSevice.getData();
    if(callback){
        dataSevice.addListener(function(data){
            callback(data);
        });
    }
    return data;
};
var halloDataStatic = dataSevice.getData();

var World = React.createClass({
    render: function() {
        return <strong>{this.props.data.value}</strong>;
    }
});

var Hello = React.createClass({
    getInitialState: function() {
        var data;
        if(typeof this.props.halloData === 'function'){
            data = this.props.halloData(this.updateHandler)
        }
        else data = this.props.halloData;
        return {
          data: data
        };
    },
    updateHandler: function(data) {
        this.setState({
          data: data
        });
    },
    render: function() {
        return (
            <div>
                Value {this.props.name}: <World data={this.state.data} />
            </div>
        );
    }
});
</script>

React.renderComponent(<Hello halloData={halloDataStatic} name="static"/>, document.getElementById('static'));
React.renderComponent(<Hello halloData={halloDataDynamic} name="dynamic"/>, document.getElementById('dynamic'));
票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20605309

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档