Вопрос по reactjs, javascript – Передать новые данные сервера в компонентыact.js

21

Я новичок в React.js и пытаюсь понять несколько основных понятий, чтобы решить, следует ли нам использовать эту библиотеку для нашего приложения. Моя главная проблема на самом деле обрабатывает обновление в модели, полученной с сервера.

Представьте, что у меня есть страница, на которой должны отображаться пять разных моделей. Я'Мы построили его так, как описано в этой статье:http://facebook.github.io/react/blog/2013/11/05/thinking-in-react.html, так что я "корень» компонент, где все 5 моделей пройдены и с помощью реквизита они переходят к компонентам, которые содержат эти модели. Итак, теперь обновлены 2 модели (я получаю эти события из кода моей модели, который находится за пределами реагирующих компонентов), и мне нужно отразить это в пользовательском интерфейсе. Каков наилучший способ сделать это?

Я думаю о следующих вариантах:

Запустите renderComponent с новыми данными еще раз и используйте методы реагирования DOM. Я обеспокоен этим, так как яЯ должен сделать это при любом небольшом изменении данных.Вызовите setState для компонентов, которые содержат эти модели. Таким образом, данные становятся не опорой, а состоянием, которое (из того, что я понимаю) не является хорошей практикой. Плюс я неНе вижу способа получить ссылку на дочерний компонент за пределами корневого компонента.Имея несколько вызовов renderComponent, поэтому у меня будет доступ к setProps для любого из этих компонентов. Но тогда мне нужно будет выполнить некоторую шаблонную работу (чтобы все контейнеры были доступны на странице), и это убивает всю идею реакции.Наличие одного корневого компонента, который включает в себя все возможные модели в приложении, отображается для пользователей и вызывает setProps для смены моделей. Мое беспокойство здесь, что этот компонент вырастет довольно большой и станетспагетти" в какой-то момент + проблемы из пункта 1.

Заранее спасибо и надеюсь, что смог четко объяснить мою проблему.

Вы нашли решение? copndz
Использует ли ваш слой модели события? если это так, вы можете использовать их для запуска рендера. krs
Мы добавили аналогичный вопрос об использовании моделей Backbone с React и о том, как следует обновлять представления при обновлении модели.stackoverflow.com/questions/20371566/... Markus-ipse

Ваш Ответ

3   ответа
4

компоненту:

Перерисовать компонент. Не беспокойтесь об эффективности этого метода, потому что React справляется с этим очень хорошо. Есть хорошие статьи об этом:Изменение и его обнаружение в JavaScript а такжеОбновление с помощью React.renderИспользуйте PubSub, чтобы позволить компоненту получать уведомления об изменении данных (некоторые полезные примеры вы можете найти вКак общаться между компонентами React сообщение).Связывание с обратным вызовом (см. Три jsfiddles ниже)

Для третьего варианта меня вдохновил ответStevenH и немного продлил Пожалуйста, проверьте мою реализацию на jsfiddle.net/kb3gN/12002/.

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}">
            </world></div>
        );
    }
});

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

Также есть расширенная версия наjsfiddle.net/kb3gN/12007.

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}">
            </world></div>
        );
    }
});

React.renderComponent(<hello dataservice="{dataSevice}">, document.body);
</hello>

Эта реализация не полностью следует идее изолированных компонентов (поскольку компонент Hello зависит от API-интерфейса DataService), но ее можно абстрагировать дальше и решать разработчику приложений, какие соглашения для конкретных приложений будут следовать его компонентам. Например, см. Смесь первого и второго примеров наjsfiddle.net/kb3gN/12015 (объект halloDataStatic и обратный вызов halloDataDynamic)

Примечание. Служба ListenersService, использованная в этом примере, следует шаблону наблюдателя, и сам шаблон во многих сценариях имеет больше недостатков, чем плюсов. Но помимо этого я хотел показать на этих примерах, что существует способ привязки данных с обратным вызовом.

<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(liste,ners.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'));
</hello></hello>
5

но с другими данными эквивалентен вызову component.setProps (). Так что либо сохраняйте все модели как состояние в наименее общем знаменателе, либо просто вызывайте setProps / renderComponent снова, когда он изменяется.

У вас есть только один корневой компонент, который вы создаете через renderComponent? Или у вас есть отдельные компоненты, которые визуализируются в разные контейнеры для каждой логической части вашего приложения? Спасибо за ответ и за попытку помочь мне! Sergey Shvets
4

вы можете просто обновить их на более высоком уровне, и это заставит выполнять рендеринг для всех компонентов, которые используют один и тот же объект свойства. Рассмотрим этот простой пример:

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>
            </world></div>
        );
    }
});

Теперь, когда пользователь нажимает кнопку, вы меняете свойство наHello компонента, но так как вы передали тот же объект свойства (или данные) дочерним элементам, они будут реагировать на него и обновлять егос тенью DOM соответственно.

Вот что я имею в виду:http://jsfiddle.net/xkCKR/

Если у вас есть внешний объект данных, вы можете просто передать его верхнему компоненту. Просто помните, что это неЭто означает, что существует двусторонняя привязка:

// 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>
            </world></div>
        );
    }
});

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

Это работает, потому что реагирует использует одностороннее связывание свойств. Но если, скажем, ваш дочерний компонент обновит егосвойства, он выигралподняться к немус родителем. За это тыпонадобитсяReactLink дополнение или используйте интерфейс pub / sub, подобный тому, который предоставляет Backbone.

Все еще не понимает взаимодействие с данными (например, вызывает сервер для получения обновленных данных). Где это играет в жизненный цикл React.js? Я полагаю, ты нея не хочу делать ajax-вызовы внутри React.js. Где это обрабатывается? Ryan
Вы'Если вы не должны менять реквизиты, вы должны отражать любые изменения в данных, вызывая setState, только это вызовет повторную визуализацию затронутых компонентов и подкомпонентов. markus
да, а также я не понимаю одностороннюю концепцию, здесь одна привязка к выстрелу, однажды выполненная, даже если я изменяю данные во внешней модели, это не влияет на визуализированный класс: this.props.model.modelproperty is не проверяется на наличие обновлений Daniele Cruciani
Все, что вы делаете здесь изнутри React, и я думаю, что операционист хочет, чтобы "обновить» Дом со стороны реагирует. copndz

Похожие вопросы