React 生命周期中的中间件如何工作?

How middleware in react life cycle works?

我是 React js 的新手。我已经开始用 react-redux 做一个小产品。我正在使用 saga 中间件。

我所做的如下。 这是组件

    //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));

行动是

    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
        }
    }

减速器是

    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;
    }

传奇是

    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;

我只能在渲染功能中获得产品道具。我怎样才能在构造函数中得到它? 如果有人向我解释更多有关 React 生命周期的信息,我将不胜感激。 谢谢。

已更新

你只需要安慰 props 而不是 this.props。你不应该在构造函数中引用 propsthis

改为这样做:

console.log(props)

中间件与 React 生命周期完全无关,除了它更新和连接的组件“反应”到 props 更新。

检查构造函数文档

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

问题:你为什么要尝试在构造函数中记录道具?如果您想知道道具是什么,请使用生命周期函数之一,componentDidMount/componentDidUpdate,不要使用渲染函数来产生副作用,例如进行异步调用或控制台日志。

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

如果您 必须 在构造函数中记录 props,访问作为组件传递的 props 对象还没有 this.props 填充。

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

在对象实例化期间调用构造函数。根据 docs“React 组件的构造函数在安装之前被调用”。因此,如果传递给组件的道具在安装组件后发生变化,您可以使用 componentWillReceiveProps 生命周期方法。

componentWillReceiveProps 已弃用,因此您可以改用 componentDidUpdate。来自文档的示例。

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: 中间件只是在动作被分派之后和它到达减速器之前出现在流程之间,就像你的情况一样,一旦你触发 onLoad 动作并且在它到达之前减速器,它被 Saga 中间件捕获,它根据其中编写的代码执行它

您案例中的生命周期如下:

  1. 在您的 compoenentDidMount 方法中,您发送了一个 onLoad 动作。这种情况下的动作类型变为“FETCH_PRODUCT”并且相同的动作现在在 Saga 中被捕获。

  2. 由于这是异步调用,因此组件中的代码会继续执行,而 Saga 会并行执行其操作。它通过这行代码调用 API : yield call(agent.Products.get, action.payload); 。一旦 API 调用完成,它会通过这行代码 yield put(productFetched({ payload: response }));.

    调度一个动作 'productfetched'
  3. 现在这个动作到达reducer并修改“products”的状态。由于您的 redux 中的产品状态已修改,因此您的组件 EcommerceProductEdit 会重新呈现,并且您会在 render 方法中获得产品列表。需要注意的是,此时流程必须已经在 componentDidMount 方法内部执行完毕,因此没有机会获得产品 their

您的问题的解决方法:

  1. 一旦一个动作被分派并且由于 Saga 而变得异步,如果你使用 Saga,你将无法在构造函数中获取值。您可以使用 componentDidMount 中的 axios/fetch 库直接调用 API 并等待它们(使其同步)。收到回复后,您可以继续下一步

  2. 如果你有功能组件,那么你可以使用 Effect hook 并将依赖项绑定到产品状态。您可以在此块中编写代码,在 API 调用和产品列表修改后要执行的代码。

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