2015-11-06 22 views
9

Ich habe einen einfachen Router (gestartet mit redux-router und auf react-router geschaltet, um Variablen zu eliminieren).react-redux connect() mapStateToProps wird mehrfach auf react-routersnavigation aufgerufen

<Router history={history}> 
    <Route component={Admin} path='/admin'> 
    <Route component={Pages} path='pages'/> 
    <Route component={Posts} path='posts'/> 
    </Route> 
</Router> 

Admin-Komponente ist im Grunde nur {this.props.children} mit etwas nav; Es ist keine connect Ed-Komponente.

Seiten-Komponente ist eine connect ed Komponente mit mapStateToProps() wie so:

function mapStateToProps (state) { 
    return { 
    pages: state.entities.pages 
    }; 
} 

Beiträge ist noch interessanter:

function mapStateToProps (state) { 
    let posts = map(state.entities.posts, post => { 
    return { 
     ...post, 
     author: findWhere(state.entities.users, {_id: post.author}) 
    }; 
    } 

    return { 
    posts 
    }; 
} 

Und dann, wenn ich die Seite zu laden oder wechseln zwischen Beiträge/Seiten Routen Ich erhalte Folgendes in meiner console.log().

// react-router navigate to /posts 

Admin render() 
posts: map state to props 
Posts render() 
posts: map state to props 
Posts render() 
posts: map state to props 

// react-router navigate to /pages 

Admin render() 
pages: map state to props 
Pages render() 
pages: map state to props 

Also meine Frage ist: Warum ist mapStateToProps mehrmals auf Routenänderungen aufgerufen wird?

Warum funktioniert auch eine einfache map Funktion in mapStateToProps verursachen es ein drittes Mal in der Posts Container aufgerufen werden?

Ich verwende die grundlegenden logger und crashReporter Middleware von den Redux-Dokumenten und es meldet keine Statusänderungen oder Abstürze. Wenn sich der Status nicht ändert, warum werden die Komponenten mehrfach gerendert?

+1

Irgendwelche Updates dazu, zufällig? –

+0

Ehrlich, nein. Ich fing an, verschiedene Dinge zu entfernen, um zu sehen, was sie auslösen könnte. Ich habe es nur noch einmal angeschaut und es scheint, als würde die Redux-Aktion "@@ INIT" eine zusätzliche Zeit auslösen, aber es ist schwer, diese Aktion zu protokollieren. Beim Rendern auf dem Server wird nur ein einzelner 'mapStateToProps' pro Container protokolliert.Hoffte auf eine Antwort von @DanAbramov – Mike

+0

Ich schaute auch auf das Redux-Beispiel der realen Welt, um zu sehen, wie oft mapStateToProps dort aufgerufen wird und es viele Anrufe einrichtet. Ich denke, es ist nicht so wichtig, solange Sie ein Tool wie [Neu auswählen] (https://github.com/rackt/reselect) verwenden, um Ihre Selektoren zu erstellen. – Mike

Antwort

0

Reselect Mit dieser Option können Sie Merker-Selektorfunktionen für die Verarbeitung des abgeleiteten Status erstellen.

Redux's documentation erklärt mit einem Beispiel, wie man es benutzt. Die Readme-Datei des Repos enthält ebenfalls ein schnelles Beispiel.

+1

habe ich das vor langer Zeit gelöst, aber Ich werde diese Antwort akzeptieren, da Reselect eine großartige Bibliothek ist. – Mike

8

Nach der Erfahrung mit react-redux sollten Sie keine Speicherattribute in mapStateToProps, da connect uses shallow checking of bound store attributes to check for diff.

Um zu überprüfen, ob Ihre Komponente aktualisiert werden muss, ruft react-reduxmapStateToProps auf und überprüft die Attribute der ersten Ebene des Ergebnisses. Wenn einer von ihnen geändert wurde (=== Gleichheitsprüfung), wird die Komponente mit den neuen Requisiten aktualisiert. In Ihrer Situation posts ändern (map Transform) jedes Mal wird aufgerufen, so dass Ihre Komponente bei jedem Wechsel des Geschäfts aktualisiert wird!

Ihre Lösung wäre, nur direkte Verweise Ihres Shops Attribute zurückgeben:

function mapStateToProps (state) { 
    return { 
    posts: state.entities.posts, 
    users: state.entities.users 
    }; 
} 

Dann in Ihrer Komponente, könnten Sie eine Funktion definieren, die Ihre Daten bei Bedarf verarbeitet:

getPostsWithAuthor() { 
    const { posts, users } = this.props; 

    return map(posts, post => { 
    return { 
     ...post, 
     author: findWhere(users, {_id: post.author}) 
    }; 
    }); 
} 
+0

es sieht aus wie Ihr GitHub-Link ist tot .... beziehen Sie sich auf diese Zeile? https://github.com/reactjs/react-redux/blob/db91ed900107e58c15000e2a45c29e85c63ca2eb/src/connect/connect.js#L36 – sfletche

+0

In der Tat hat sich der Code von 'connect.js' bewegt und viel geändert, danke @sfletche für Benachrichtigen! Beachten Sie, dass 'connect' nun benutzerdefinierte Update-Bedingungen zu akzeptieren scheint, so dass OP sie tatsächlich gezielt anpassen kann (obwohl ich empfehle, nichts in' mapStateToProps' zu transformieren, aber im letzten Moment innerhalb der Komponente) – blint

Verwandte Themen