2017-03-18 1 views
0

J'ai donc eu du mal à comprendre l'écosystème de réaction-redux pendant un moment maintenant. Je suis presque là mais il y a encore quelque chose qui continue à me donner des problèmes, et c'est la méthode componentDidUpdate. Lorsque j'expédie une action asynchrone, le magasin est appelé correctement et l'état du composant est mis à jour.componentDidUpdate ne se déclenche pas

Mais pour une raison quelconque, la méthode componentDidUpdate ne se déclenche pas, il n'y a pas de rendu, et je ne peux pas accéder aux accessoires mis à jour. Je peux le voir changer dans devtools, si je console.log (this.props.blogStore). Au début, il montre comme un objet vide, mais quand on clique dessus, il s'ouvre et montre l'état mis à jour.

J'ai essayé autant de méthodes de cycle de vie que possible, mais rien ne semble fonctionner, y compris componentWillReceiveProps.

Une idée de ce que je fais mal?

Voici le code:

index.js

import React from 'react'; 
import ReactDOM from 'react-dom'; 
import { Provider } from 'react-redux'; 

import App from './App'; 
import Datastore from 'Datastore'; 

const store = Datastore() 

store.subscribe(() => console.log("state changed", store.getState())) 

ReactDOM.render(
    <Provider store={store}> 
     <App /> 
    </Provider>, 
    document.getElementById('app') 
); 

Datastore.js

import { combineReducers, createStore, applyMiddleware } from 'redux'; 
import thunk from 'redux-thunk' 

import Mainmenu from 'reducers/Mainmenu'; 
import Blogstore from 'reducers/Blogstore'; 

const reducer = combineReducers({ 
    Mainmenu, 
    Blogstore, 
}) 

export default function Datastore() { 
    const store = createStore(
     reducer, 
     applyMiddleware(thunk) 
    ) 

    return store 
} 

réducteur

import Article from 'lib/Article'; 
import { ARTICLE_LOAD, ARTICLE_UPDATE, SAVE_ARTICLE_LIST } from 'actionTypes'; 

const initialBlogState = { 
} 

const Blogstore = (state=initialBlogState, action) => { 
    switch(action.type) { 
     case SAVE_ARTICLE_LIST: 
      state.init = true 
      state.articles = action.payload 
      return state 
     case ARTICLE_LOAD: 
      return state 
     case ARTICLE_UPDATE: 
      return state 
    } 
    return state 
} 

export default Blogstore; 

Blog-actions.js

import { ARTICLE_LOAD, ARTICLE_UPDATE, SAVE_ARTICLE_LIST } from 'actionTypes'; 
import APIFetch from '../lib/Fetch'; 

export function getArticlePids() { 
    return dispatch => { 
     APIFetch().get("/blog/list").then(response => { 
      dispatch({ 
       type: SAVE_ARTICLE_LIST, 
       payload: response.data 
      }) 
     }) 
    } 
} 

composant

import React from 'react'; 
import { connect } from 'react-redux'; 
import * as blogActions from '../actions/blog-actions'; 

@connect(state => ({ 
    blogStore: state.Blogstore 
})) 
export default class Blog extends React.Component { 
    constructor() { 
     super() 
    } 

    componentDidMount() { 
     this.props.dispatch(blogActions.getArticlePids()) 
    } 

    componentDidUpdate(prevProps) { 
     console.log("update", prevProps) 
    } 

    render() { 
     console.log("render", this.props.blogStore) 

     return (
      <div><h1>Blog</h1></div> 
     ) 

    } 
} 

C'est à peu près tout. Je ne vais pas tracasser l'App et le Router qui sont entre index.js et le composant car il n'y a rien d'intéressant. Juste un routeur de base de réaction et des composants qui n'ont rien à voir avec cela.

+0

Je pense que la fonction render a besoin de retourner un résultat différent pour que la réconciliation pour détecter les changements: https://facebook.github.io/react/docs/react-component.html#componentdidupdate donc sur votre fonction de retour, vous devez retourner quelque chose comme:

{this.props.blogStore}
pour que cela fonctionne – ospfranco

+0

Pourriez-vous également poster votre réducteur? On dirait que vous avez un effet secondaire quelque part. – Shota

+0

@Shota Bien sûr, juste inclus dans le bloc de code. C'est très simple, car je ne fais que tester des choses pour essayer de tout faire fonctionner. – Cory

Répondre

3

Vous devez retourner un nouvel objet de votre réducteur, comme ceci:

import Article from 'lib/Article'; 
import { ARTICLE_LOAD, ARTICLE_UPDATE, SAVE_ARTICLE_LIST } from 'actionTypes'; 

const initialBlogState = { 
} 

const Blogstore = (state=initialBlogState, action) => { 
    switch(action.type) { 
     case SAVE_ARTICLE_LIST: 
      return Object.assign({}, state, { 
       init: true, 
       articles: action.payload, 
      }) 
     case ARTICLE_LOAD: 
      return state 
     case ARTICLE_UPDATE: 
      return state 
    } 
    return state 
} 

export default Blogstore; 

Sinon, si vous essayez de mettre à jour directement votre état (comme vous le faites actuellement) il ne mute la référence interne les composants d'état et de réaction ne seront pas en mesure de détecter le changement et ne seront pas rendus. Read more here.

+0

Ahhh ... okay maintenant je vois. En fait, je pensais que c'était ce que je faisais. Lecture éclairante. Merci, ça marche bien maintenant. – Cory