根据子组件在<app>级别更改React状态的最佳方法

时间:2018-01-04 22:11:02

标签: javascript reactjs react-router react-router-v4 react-component

我有一个具有顶级<App />组件的React应用程序(从create-react-app开始构建)。我的顶级组件看起来像这样:

<Header title={this.state.appTitle} theme={this.state.theme} />
<Switch>
  {routes.map((route, index) => <Route key={index} {...route} />)}
  <Route component={NotFound} />
</Switch>

routes是{component:,to:}对象的数组。由<Route>呈现的每个组件都使用一个名为<Page>的子组件,我在其中设置标题并包装一些内容:

<Page title="About Us">
  <p>Content here</p>
</Page>

有时页面可能会使用不同的主题,我想在查看该页面时将其应用于<Header />

<Page title="About Us" theme="alt">

我希望做的是在呈现每个组件时在appTitle中更改theme<App />状态。做这个的最好方式是什么?使用React的生命周期钩子之一?还有其他方法可以改变“顶级”状态吗?如果是,我如何将操作传递给通过反应路由器<Route>组件?

2 个答案:

答案 0 :(得分:2)

您可以将函数传递给每个组件,并在使用componentDidMount生命周期方法挂载每个子项时调用该函数。

<Switch>
  {routes.map((route, index) => {
    const Comp = route.component;
    return <Route
      key={index}
      { ...route}
      // overwrite the component prop with another component
      component={
        (routeProps) => (
          <Comp
            {...routeProps}
            childHasMounted={() => this.setState({ name: route.name })}
          />
        ) 
      }
    />
  })}
  <Route component={NotFound} />
</Switch>

// child.js
class Child extends React.Component {
  componentDidMount() {
    this.props.childHasMounted();
  }
}

答案 1 :(得分:1)

翻转头部的结构。拥有每一个&#34;页面&#34;组件控制自己的布局。

制作布局更高阶的组件(获取组件类并返回组件类的函数):

function LayoutHOC({ title, theme, component: ContentComponent }) {
    return class LayoutWrapper extends React.Component {
        render() {
            return (
                <div>
                    <Header title={title} theme={theme} />
                    <Page title={title} theme={them}>
                        <ContentComponent {...this.props} />
                    </Page>
                </div>
            )
        }
    }
}

使文件夹结构域具体,如pages/about/MyAboutPage.jsx中所示,以保存主要组件内容。

然后创建pages/about/index.js并导出包含在布局高阶组件中的内容组件。

index.js

import MyAboutPage from './MyAboutPage';
export default LayoutHOC({ title: 'my title', theme: 'alt', component: MyAboutPage })

然后在你的路线中你可以import About from './pages/about'(因为它使用index.js你不必担心嵌套的文件夹结构)。

缺点是你必须为每个域/路由创建一个index.js.好处是你的内容组件不知道它的布局,并且每个页面/路由都可以控制它自己的页眉/页脚。

这种模式是从this React boilerplate project

中窃取的