2015-11-06 18 views
9

Ho un router semplice (avviato con redux-router e passato a react-router per eliminare le variabili).React-redux connect()'s mapStateToProps viene chiamato più volte nella navigazione react-router

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

Il componente di amministrazione è in pratica solo {this.props.children} con un po 'di navigazione; non è un componente di connect ed. componente

Pages è un componente connect ED con mapStateToProps() in questo modo:

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

messaggi è ancora più interessante:

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

    return { 
    posts 
    }; 
} 

e poi quando ho caricare la pagina o passare messaggi/percorsi Pages Ottengo il seguente nel mio 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 

Quindi la mia domanda è: perché è mapStateToProps viene chiamato più volte su cambiamenti di rotta?

Inoltre, perché una semplice funzione map in mapStateToProps causa che venga chiamata una terza volta nel contenitore Post?

Sto utilizzando i middleware di base logger e crashReporter dai documenti di Redux e non sta segnalando modifiche di stato o arresti anomali. Se lo stato non cambia, perché i componenti vengono visualizzati più volte?

+1

Eventuali aggiornamenti su questo, per caso? –

+0

Onestamente, no. Ho iniziato a rimuovere cose diverse per vedere cosa poteva scatenarlo. L'ho solo guardato di nuovo e sembra che l'azione '@ INIT IN di Redux lo licenzi un altro tempo, ma è difficile registrare quell'azione. Durante il rendering sul server registra solo un singolo 'mapStateToProps' per container.Speravo nella risposta di @DanAbramov – Mike

+0

Ho anche guardato l'esempio del mondo reale di Redux per vedere quante volte mapStateToProps viene chiamato lì e crea molte chiamate. Sto pensando che non è così importante finché usi uno strumento come [Riseleziona] (https://github.com/rackt/reselect) per memorizzare i tuoi selettori. – Mike

risposta

0

Reselect consente di creare funzioni di selezione memoizzate per l'elaborazione dello stato derivato.

Redux's documentation spiega con un esempio come utilizzarlo. Anche i readme del repository hanno un rapido esempio.

+1

Ho risolto questo molto tempo fa, ma accetterò questa risposta dal momento che Reselect è una grande libreria. – Mike

8

Per esperienza con react-redux, non è necessario elaborare gli attributi del negozio all'interno di mapStateToProps perché connect uses shallow checking of bound store attributes to check for diff.

Per verificare se il componente deve essere aggiornato, react-redux chiama mapStateToProps e controlla gli attributi di primo livello del risultato. Se uno di questi viene modificato (controllo di uguaglianza ===), il componente si aggiorna con i nuovi oggetti di scena. Nella tua situazione posts cambia (map transform) ogni volta che mapStateToProps viene chiamato, quindi il tuo componente viene aggiornato ad ogni cambio di negozio!

La soluzione potrebbe essere quella di restituire solo riferimenti diretti degli attributi del vostro negozio:

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

Poi nel componente, è possibile definire una funzione che elabora i dati su richiesta:

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

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

sembra che il tuo link github sia morto .... ti riferisci a questa linea? https://github.com/reactjs/react-redux/blob/db91ed900107e58c15000e2a45c29e85c63ca2eb/src/connect/connect.js#L36 – sfletche

+0

In effetti, il codice di 'connect.js' si è spostato e modificato molto, grazie @sfletche per notifica! Si noti che 'connect' sembra accettare le condizioni di aggiornamento personalizzate ora, quindi OP potrebbe effettivamente modificarle in modo specifico (anche se consiglio di non trasformare nulla in' mapStateToProps' ma all'ultimo momento all'interno del componente) – blint

Problemi correlati