2017-02-20 4 views
0

Ich habe angefangen mit react-redux und finde es eine sehr interessante Möglichkeit, um den Front-End-Code für eine Anwendung mit vielen Objekten zu vereinfachen, die es von einem Back-End-Service erhält, wo die Objekte am Frontend aktualisiert werden müssen in ungefähr Echtzeit.Warum kann ich eine Reaktionskomponente nicht curren?

Die Verwendung einer Containerklasse automatisiert das Beobachten weitgehend (wodurch die Objekte im Geschäft aktualisiert werden, wenn sie sich ändern). Hier ein Beispiel:

const MethodListContainer = React.createClass({ 
    render(){ 
    return <MethodList {...this.props} />}, 

    componentDidMount(){ 
    this.fetchAndWatch('/list/method')}, 
    componentWillUnmount(){ 
    if (isFunction(this._unwatch)) this._unwatch()}, 

    fetchAndWatch(oId){ 
    this.props.fetchObject(oId).then((obj) => { 
     this._unwatch = this.props.watchObject(oId); 
     return obj})}}); 

Bei dem Versuch, den Rest der Anwendung mit möglichst einfacher und klarer Trennung wie möglich zu liefern, habe ich versucht, ein alternative ‚connect‘ zu liefern, die automatisch einen geeigneten Behälter so liefern würde:

const connect = (mapStateToProps, watchObjectId) => (component) => { 
    const ContainerComponent = React.createClass({ 
    render(){ 
     return <component {...this.props} /> 
    }, 

    componentDidMount(){ 
     this.fetchAndWatch()}, 
    componentWillUnmount(){ 
     if (isFunction(this._unwatch)) this._unwatch()}, 

    fetchAndWatch(){ 
     this.props.fetchObject(watchObjectId).then((obj) => { 
     this._unwatch = this.props.watchObject(watchObjectId); 
     return obj})} 
    }); 
    return reduxConnect(mapStateToProps, actions)(ContainerComponent) 
}; 

Diese wird dann so verwendet:

module.exports = Verbindung (mapStateToProps, '/ list/method') (method)

jedoch component wird nicht gerendert. Der Container wird gerendert, außer dass die component nicht instanziiert oder gerendert wird. Die component wird wie erwartet gerendert (und aktualisiert), wenn ich sie nicht als Parameter übergebe und stattdessen direkt referenziere.

Es werden keine Fehler oder Warnungen generiert.

Was mache ich falsch?

Antwort

0

Verwenden Sie einen anderen Variablennamen für den Parameter component.

const connect = (mapStateToProps, watchObjectId) => (MyComponent) => { 
    const ContainerComponent = React.createClass({ 
    render() { 
     return <MyComponent {...this.props} obj={this.state.obj} /> 
    } 
    ... 
    fetchAndWatch() { 
     fetchObject(watchObjectId).then(obj => { 
     this._unwatch = watchObject(watchObjectId); 
     this.setState({obj}); 
     }) 
    } 
    }); 
    ... 
} 

Ich denke, das Problem sein könnte, da die Komponente in Kleinschreibung (<component {...this.props} />). JSX behandelt Kleinbuchstabenelemente als DOM-Element und aktiviert es als React-Element.

Edit:

Wenn Sie die obj Daten zugreifen müssen, werden Sie es als Requisiten an die Komponente übergeben. das Code-Snippet aktualisiert

+0

Danke für den Vorschlag. Dies machte jedoch keinen Unterschied. –

+0

Ich sehe kein Problem mit der Art und Weise, wie Sie die HOC strukturieren, abgesehen von dem, worauf ich hingewiesen habe. Ich nehme an, dass 'reduxConnect' ein Alias ​​des redux connect 'import {connect als reduxConnect} von 'react-redux' ist;' – jpdelatorre

+0

Es ist. Ich kann das Problem auch nicht sehen, weshalb ich die Frage (nach vielen Experimenten) gestellt habe. Die Problemumgehung in meiner eigenen Antwort hat mich durch, aber ich muss es ändern, um mapStateToProps zu übergeben (und zu erweitern). –

0

Dies ist meine Abhilfe eher als eine Erklärung für den Fehler:

In connect_obj.js:

"use strict"; 
import React from 'react'; 
import {connect} from 'react-redux'; 

import {actions} from 'redux/main'; 
import {gets} from 'redux/main'; 
import {isFunction, omit} from 'lodash'; 

/* 
A connected wrapper that expects an oId property for an object it can get in the store. 
It fetches the object and places it on the 'obj' property for its children (this prop will start as null 
because the fetch is async). It also ensures that the object is watched while the children are mounted. 
*/ 

const mapStateToProps = (state, ownProps) => ({obj: gets.getObject(state, ownProps.oId)}); 

function connectObj(Wrapped){ 
    const HOC = React.createClass({ 
    render(){ 
     return <Wrapped {...this.props} /> 
    }, 

    componentDidMount(){ 
     this.fetchAndWatch()}, 
    componentWillUnmount(){ 
     if (isFunction(this._unwatch)) this._unwatch()}, 

    fetchAndWatch(){ 
     const {fetchObject, watchObject, oId} = this.props; 
     fetchObject(oId).then((obj) => { 
     this._unwatch = watchObject(oId); 
     return obj})}}); 
    return connect(mapStateToProps, actions)(HOC)} 

export default connectObj; 

Dann kann ich es überall benutzen also:

"use strict"; 
import React from 'react'; 

import connectObj from 'redux/connect_obj'; 

const Method = connectObj(React.createClass({ 
    render(){ 
    const {obj, oId} = this.props; 
    return (obj) ? <p>{obj.id}: {obj.name}/{obj.function}</p> : <p>Fetching {oId}</p>}})); 

So connectObj erreicht mein Ziel der Erstellung eines projektweiten Ersatz für die Einrichtung der Verbindung explizit zusammen mit einer Container-Komponente zu beobachten/unwatch das Objekt ts. Das spart eine Menge Kesselplatte und gibt uns einen einzigen Ort, um das Setup und die Verbindung des Speichers zu den Komponenten aufrechtzuerhalten, deren Aufgabe es ist, nur die Objekte zu präsentieren, die sich im Laufe der Zeit ändern können (durch Aktualisierungen von dem Dienst).

Ich verstehe immer noch nicht, warum mein erster Versuch nicht funktioniert und diese Problemumgehung nicht unterstützt, andere Staatsrequisiten zu injizieren (da alle Aktionen verfügbar sind, gibt es keine Notwendigkeit, sich um die Versendungen zu kümmern).

Verwandte Themen