简体   繁体   English

react-router 渲染导致子组件无法访问构造函数中的 redux 道具

[英]react-router render causing child component to not have access to redux props in constructor

TL,DR: I need to set a default local state value based on a store value in a grandchild's constructor. TL,DR:我需要根据孙子构造函数中的store值设置默认的本地 state 值。 render vs. component . rendercomponent component lets me have access to the store in child's constructor, render does not. component让我可以访问子构造函数中的存储,而render则不能。 On redux dispatches, render does not re-mount child, component does and wipes the child's local state.在 redux 调度时, render不会重新挂载子进程, component会执行并擦除子进程的本地 state。

I have a child component in my app that has access to the redux store.我的应用程序中有一个子组件可以访问redux商店。 The problem is when I use the component={child} in Router -> Route , it's fine.问题是当我在Router -> Route中使用component={child}时,没问题。 I'm able to use the store in the child 's constructor.我可以在child的构造函数中使用 store。 However, I need to update the store ( dispatch ) in the same child and using component= is causing the child to un-mount and re-mount, wiping its local state .但是,我需要在同一个孩子中更新存储( dispatch ),并且使用component=导致孩子卸载并重新安装,擦除其本地 state The issue is here: Redux dispatch causing component local state to reset问题出在这里: Redux 调度导致组件本地 state 重置

So now I'm using render={child} but doing so, it's causing me to not have access to the store (values are null) in my child's constructor.所以现在我正在使用render={child}但这样做会导致我无法访问我孩子的构造函数中的存储(值为空)。 Here is some sample code:这是一些示例代码:

Application.jsx应用程序.jsx

render() {

        // location, match, search used for hiding elements logic
        const allTabs = ({ location, match, search }) => {

            // Parse the query string and look for the "show" keyword (this is arbitrary)
            const qs = queryString.parse(location.search, { ignoreQueryPrefix: true });

            return (
                <div>
                    { qs.hideHeader === "1" ? null : <Header environment={config.environment} user={this.props.currentUser.fullName} /> }
                    { qs.hideNav === "1" ? null : <NavigationTabs tabList={this.state.tabList} accessPermissions={this.props.currentUser.permission} /> }
                    { qs.hideContent === "1" ? null : <TabContent tabList={this.state.tabList} accessPermissions={this.props.currentUser.permission} /> }
                    { qs.hideFooter === "1" ? null : <Footer /> }
                </div>
            );
        }

        // Place this inside Router and test it. It is not working.... <Route exact path="/t/directLink?showNoHeaderFor=wfPE" component={singleTab} />
        return (
            <Router>
                <div>
                    {/* when `component` is used, can use store in child constructor */}
                    {/* when `render` is used, cannot can use store in child constructor */}
                    {/* when `render` is used, dispatches don't remount component */}
                    <Route path="/" render={allTabs} />
                </div>
            </Router>
        );
    }

TabContent.jsx -> render return TabContent.jsx -> 渲染返回

return (
            <div className="tab-content">
                <HashRouter>
                    <Switch>
                        {this.props.tabList.map(tab => {
                            return (
                                {/* i have also tried messing with render/component here, but the problem is probably in Application.jsx */}
                                <Route key={tab.id} path={`/t/${tab.url}`} component={tab.component} />
                            );
                        })}
                        { firstTabUrl !== "" ? <Redirect exact from="/" to={`/t/${firstTabUrl}`} /> : null }
                    </Switch>
                </HashRouter>
            </div>
        );

A Grand-child component, rendered by TabContent.jsx由 TabContent.jsx 呈现的 Grand-child 组件

export class PartnershipStructure extends React.Component {

    constructor(props) {
        super(props);

        // the store
        const { periods, portfolios, utilityValues } = this.props;

        // setting the default value using props
        const calendars = periods.calendars(); // <<-- value is null when `render` is used in Application.jsx

Note: I observe this issue on page refreshes .注意:我在页面刷新时观察到此问题。 It seems to be that the grandchild is getting constructed while the store is filling up.似乎是在store装满时,孙子正在建造中。 If I navigate away from the tab and back, the problem is not observed .如果我离开选项卡并返回,则不会观察到问题。 It's worth noting that using component= , I don't have this problem.值得注意的是,使用component= ,我没有这个问题。 But as stated, component= causes dispatches to re-mount.但如前所述, component=会导致调度重新挂载。

Since my aim is to set the grandchild's initial state using redux , I had to "wait" for the redux store to fill up.由于我的目标是使用redux设置孙子的初始 state ,因此我不得不“等待” redux商店填满。 I cannot do this in the constructor.我不能在构造函数中这样做。 It seems that in react, the order of events are:似乎在反应中,事件的顺序是:

  1. components are constructed and mounted组件的构建和安装
  2. fetch operations began async获取操作开始异步
  3. components are rendered组件被渲染
  4. redux updates state and updates components with new props redux 更新 state 并使用新道具更新组件

My issue is that component construction were not waiting for redux .我的问题是组件构造没有等待redux To solve this issue, I had to use the lifecycle function componentWillReceiveProps(nextProps) .为了解决这个问题,我不得不使用生命周期 function componentWillReceiveProps(nextProps) So that's the answer.所以这就是答案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM