Comment fonctionne le middleware dans React Life Cycle?

2020-06-30 reactjs react-redux redux-saga react-lifecycle

Je suis nouveau dans react js. J'ai commencé à faire un petit produit avec react-redux. J'utilise le middleware de la saga.

Ce que j'ai fait est comme ci-dessous. Ceci est le composant

    //all import work

    import { activateAuthLayout, onLoad } from '../../../store/actions';

    class EcommerceProductEdit extends Component {

        constructor(props) {
            super(props);
            this.state = {
                checked: false,
                unselected_lists: [],
                main_checked: false
            }

            //here I get the products props always null
            console.log(this.props);
        }

        componentDidMount() {
            this.props.activateAuthLayout();

            //dispatching an action to fetch data from api, done in midddleware
            if (this.props.user !== null && this.props.user.shop_id)
                this.props.onLoad({
                    payload: this.props.user
                });
        }

        render() {

            //here I get the products props 
            console.log(this.props);

            return (
            //jsx work
            );
        }
    }

    const mapStatetoProps = state => {
        const { user, is_logged_in } = state.Common;
        const { products, is_loading } = state.Products;
        return { user, is_logged_in, products, is_loading };
    }

    export default withRouter(connect(mapStatetoProps, { activateAuthLayout, onLoad })(EcommerceProductEdit));

L'action est

    import { FETCH_PRODUCT, FETCH_PRODUCT_SUCCESS } from './actionTypes';

    export const onLoad = (action) => {
        return {
            type: FETCH_PRODUCT,
            payload: action.payload
        }
    }

    export const productFetched = (action) => {
        return {
            type: FETCH_PRODUCT_SUCCESS,
            payload: action.payload
        }
    }

Le réducteur est

    import { FETCH_PRODUCT_SUCCESS } from './actionTypes';

    const initialState = {
        products: null,
        is_loading: true
    }

    export default (state = initialState, action) => {
        switch (action.type) {
            case FETCH_PRODUCT_SUCCESS:
                state = {
                    ...state,
                    products: action.payload,
                    is_loading: false
                }
                break;

            default:
                state = { ...state };
                break;
        }
        return state;
    }

Et la saga est

    import { takeEvery, put, call } from 'redux-saga/effects';
    import { FETCH_PRODUCT } from './actionTypes';
    import { productFetched } from './actions';
    import agent from '../../agent';

    function* fetchProduct(action) {
        try {
            let response = yield call(agent.Products.get, action.payload);
            yield put(productFetched({ payload: response }));
        } catch (error) {
            if (error.message) {
                console.log(error);
            } else if (error.response.text === 'Unauthorized') {
                console.log(error)
            }
        }
    }

    function* productSaga() {
        yield takeEvery(FETCH_PRODUCT, fetchProduct)
    }

    export default productSaga;

Je ne peux obtenir les accessoires des produits qu'en fonction de rendu. Comment pourrais-je l'obtenir dans le constructeur? Je serais vraiment reconnaissant si quelqu'un m'expliquait un peu plus le cycle de vie de réagir. Merci.

actualisé consoledincomponentDidMount

Answers

Il vous suffit de consoler les props plutôt que de faire this.props . Vous ne devriez pas référencer les props avec this à l'intérieur du constructeur.

Faites ceci à la place:

console.log (accessoires)

Le middleware n'est pas du tout lié à la réactivité du cycle de vie, à part sa mise à jour et les composants connectés «réagissent» à la mise à jour des accessoires.

Vérifiez les documents du constructeur

https://reactjs.org/docs/react-component.html#constructor

Question: pourquoi essayez-vous de connecter des accessoires dans le constructeur de toute façon? Si vous voulez savoir quels sont les accessoires, utilisez l'une des fonctions de cycle de vie, componentDidMount / componentDidUpdate , n'utilisez pas la fonction de rendu pour effectuer des effets secondaires comme effectuer des appels asynchrones ou le journal de la console.

componentDidMount() {
  console.log(this.props);
}

Si vous devez cependant enregistrer les accessoires dans le constructeur, accédez à l'objet d'accessoires qui a été transmis car le composant n'aura pas encore de this.props .

constructor(props) {
  super(props);
  ...
  console.log(props);
}

un constructeur est appelé lors de l'instanciation d'un objet. Selon les documents "Le constructeur d'un composant React est appelé avant son montage". Donc, si les accessoires transmis au composant sont modifiés après le montage du composant, vous pouvez utiliser les méthodes de cycle de vie de componentWillReceiveProps .

componentWillReceiveProps est obsolète, vous pouvez donc utiliser componentDidUpdate à la place. Exemple de la documentation.

componentDidUpdate(prevProps) {
  // Typical usage (don't forget to compare props):
  if (this.props.userID !== prevProps.userID) {
    // update your component state from here.
    this.fetchData(this.props.userID);
  }
}

MiddleWare: le middleware vient juste entre le flux après que l'action a été envoyée et avant qu'elle n'atteigne les réducteurs, comme dans votre cas une fois que vous avez déclenché l'action onLoad et avant qu'elle n'atteigne les réducteurs, son middleware Saga est pris en charge qui l'exécute selon le code écrit dedans

Le cycle de vie dans votre cas se déroule comme suit:

  1. Dans votre méthode compoenentDidMount, vous envoyez une action de onLoad. Le type d'action dans un tel cas devient "FETCH_PRODUCT" et la même action est maintenant interceptée dans Saga.

  2. Comme il s'agit d'un appel asynchrone, le code de votre composant continue de s'exécuter pendant que la Saga effectue son action en parallèle. Il appelle l'API via cette ligne de code: yield call(agent.Products.get, action.payload); . Une fois l'appel d'API terminé, il envoie une action «productfetched» via cette ligne de code yield put(productFetched({ payload: response })); .

  3. Maintenant, cette action atteint le réducteur et modifie l'état des "produits". Étant donné que l'état du produit dans votre redux est modifié, votre composant EcommerceProductEdit nouveau rendu et vous obtenez votre liste de produits dans la méthode de rendu. Le point à noter est que le flux doit avoir déjà fini de s'exécuter à l'intérieur de la méthode componentDidMount à ce moment, donc aucune chance d'avoir des produits leur

Solution à votre problème:

  1. Une fois qu'une action est envoyée et qui est devenue asynchrone à cause de Saga, vous ne pourrez pas obtenir de valeur dans le constructeur, si vous utilisez Saga. Vous pouvez simplement appeler directement l'API en utilisant la bibliothèque axios / fetch dans componentDidMount et attendre leur (Rendre synchrone). Une fois que vous obtenez une réponse, vous pouvez continuer

  2. Si vous avez un composant fonctionnel, vous pouvez utiliser le hook Effect et lier la dépendance à l'état des produits. Vous pouvez écrire votre code dans ce bloc, ce que vous souhaitez exécuter après l'appel de l'API et la modification de la liste des produits.

     React.useEffect(
    
     () => {
         // You code goes here
     },
     [products]
     );
    

Related