【问题标题】:Redux state not dispatched on page loadRedux 状态未在页面加载时分派
【发布时间】:2021-11-28 20:10:54
【问题描述】:

我找不到页面加载时我的redux状态没有被调度的原因,即使组件挂载时有调度事件

这是我的问题的一个基本示例:

export const SET_SITE_NAME = "SET_SITE_NAME";

动作:

import {SET_SITE_NAME} from "./AppBarTypes";

export const setSiteName = (state) => dispatch => {
    dispatch({
        type: SET_SITE_NAME,
        payload: state
    })
}

减速机:

import {SET_SITE_NAME} from "./AppBarTypes";

const initialState = {
    state: "Dashboard"
}

export const appBarReducer = (state = initialState, action) => {
    switch(action.type) {
        case SET_SITE_NAME:
            return {
                ...state,
                state: action.payload
            };
        default:
            return state;
    }
}

基本用法:

function ProjectsList(props) {
   
    useEffect(() => {
        props.setSiteName("Projects");
    }, []);

    return (
        <Main open={props.drawer.state}>
        </Main>
    );
}

ProjectsList.propTypes = {
    setSiteName: PropTypes.func.isRequired
};

const mapStateToProps = state => ({
    projects: state.projects,
    drawer: state.drawer
});

export default connect(mapStateToProps, {
    getProjects,
    setSiteName
})(withRouter(ProjectsList));

根据我能够调试的情况,setSiteName 函数运行并且它始终接收正确的状态。 另外,如果我导航到站点上的其他组件并返回到该组件,它会完美地加载状态,因此我认为实现是正确的。

编辑

我创建了一个可以追溯问题的工作示例。 https://stackblitz.com/edit/react-sf1fmj?file=src%2FApp.js

问题与useMediaQuery 有关。正如您在示例中看到的那样,如果您取消注释该部分,将显示默认的 redux 状态“仪表板”而不是设置的“项目”状态。

虽然我不知道为什么会导致这个问题以及如何解决它。正如你所看到的,在这个例子中我什至没有使用那个值,只是查询它......

【问题讨论】:

  • 你能在stackblitz.com 上创建一个最小的工作示例吗?如果可能的话。这对跑步和回答很有帮助。
  • 我尝试过重新创建相同的应用程序,但它甚至不会从这里开始:stackblitz.com/edit/react-ix62ac?file=src/Demo.js 虽然您可以清楚地看到状态设置为减速器状态
  • 好吧,我已经解决了 stackblitz.io 上的问题,并且它在那里完美地工作......虽然在我的项目中它要复杂得多,所以我不知道什么会导致这样的副作用.
  • 我找到了错误,但我不知道为什么会这样:stackblitz.com/edit/react-sf1fmj?file=src%2FApp.js 如果我使用useMediaQuery 来检查暗模式,您可以在示例中看到返回“Hello Dashboard” (默认的 redux 状态)。如果你删除它,它就可以正常工作。

标签: reactjs redux react-redux


【解决方案1】:

我认为您缺少 React Thunk 到您的中间件 https://github.com/reduxjs/redux-thunk。 这样,您可以使用以下语法:

function incrementAsync() {
  return dispatch => {
    setTimeout(() => {
      // Yay! Can invoke sync or async actions with `dispatch`
      dispatch(increment())
    }, 1000)
  }
}

编辑

我相信你错过了调度......你基本上可以通过两种方式做到这一点:直接调用调度来调度你的动作,或者,使用 mapDispatchToProps 函数映射你的调度动作,如下所示:


const mapDispatchToProps = (dispatch) => ({
    siteName: ()=> dispatch(siteNameAction())
})


export default connect(mapStateToProps, mapDispatchToProps)(MyComponent)

所以使用上面显示的方法,你可以简单地调用this.props.siteName()

【讨论】:

  • 对不起,我忘了包括这个,但我认为它在那里:const middleware = [thunk, routerMiddleware(history)]; const store = createStore( rootReducer(history), applyMiddleware(...middleware), );
  • @KristofRado 所以在这种情况下我相信你错过了你的“matchDispatchToProps”。我将把它包括在我的答案中。
  • 请看这个例子:stackblitz.com/edit/react-ix62ac?file=src/Demo.js 这就是它的基本设置方式,在这里完美运行。所以我假设我的这部分代码是正确的,所以问题可能出在其他地方(这个剥离版本中不包含)。
  • 问题与设置暗模式有关
【解决方案2】:

我需要改变这个:

const prefersDarkMode = useMediaQuery('(prefers-color-scheme: dark)');

到这里:

const prefersDarkMode = useMediaQuery('(prefers-color-scheme: dark)', { noSsr: true });

Metarial UI useMediaQuery hooks render twice to React Component, do you have any solution for it?

根据文档,如果您不进行任何服务器端渲染,则可以将其设置为 false:

Options.noSsr(布尔 [可选]):默认为 false。为了执行服务器端渲染协调,它需要渲染两次。第一次什么都没有,第二次和孩子们在一起。这种双通道渲染周期有一个缺点。它更慢。如果您不进行服务器端渲染,则可以将此标志设置为 true。

【讨论】:

    猜你喜欢
    • 2022-09-23
    • 2020-11-09
    • 1970-01-01
    • 2019-12-23
    • 2017-04-04
    • 2018-09-03
    • 2020-04-22
    • 2021-04-13
    • 2021-12-25
    相关资源
    最近更新 更多