【问题标题】:Best way to change React state at <App /> level based on sub-components基于子组件在 <App /> 级别更改 React 状态的最佳方法
【发布时间】:2018-06-14 17:14:05
【问题描述】:

我有一个 React 应用程序,它有一个顶级 &lt;App /&gt; 组件(从 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: } 个对象的数组)。 &lt;Route&gt; 渲染的每个组件都使用了一个名为 &lt;Page&gt; 的子组件,我在其中设置了标题并包装了一些内容:

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

有时页面可能使用不同的主题,我想在查看该页面时将其应用于&lt;Header /&gt;

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

我要做的是在渲染每个组件时更改&lt;App /&gt; 中的appTitletheme 状态。做这个的最好方式是什么?使用 React 的生命周期钩子之一?改变“顶级”状态的其他方法?如果是这样,我如何通过 react-router &lt;Route&gt; 组件将操作传递给这些组件?

【问题讨论】:

  • 您是否希望this.state/传递给标头的道具根据传递给&lt;Page /&gt;的道具进行更新?
  • @paulruescher 有效,是的。

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


【解决方案1】:

您可以将一个函数传递给每个组件,并在每个子组件挂载时调用该函数,使用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();
  }
}

【讨论】:

    【解决方案2】:

    翻转结构。让每个“页面”组件控制自己的布局。

    制作一个布局更高阶的组件(接受一个组件类并返回一个组件类的函数):

    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偷来的

    【讨论】:

    • 这太棒了。我想我担心为每个标题更改重新呈现标题。例如,我希望标题的背景在主题更改时在主题之间进行动画处理。使用 HOC 还能实现类似的功能吗?
    • 嗯,如果你完全使用 CSS 动画,我怀疑是这样,但我不确定。如果您在组件或 CSSTransitionGroup 中使用 Javascript 动画...我不知道! :O
    猜你喜欢
    • 2021-01-25
    • 2022-07-18
    • 2021-09-29
    • 1970-01-01
    • 1970-01-01
    • 2019-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多