javascript - react : Change component's children from the outside

标签 javascript reactjs

在React项目中,我有一个组件Header.js,它是全局布局的一部分,并且在每个页面上使用。路由是通过 React Router v4 完成的。

Header.js 组件应该有不同的子组件(例如面包屑或标题),具体取决于我当前所在的页面。

示例:在 HomePage.js 上,我想显示面包屑。但在 AboutPage.js 上,我只想有一个标题。

<App>
  <Header />

  <AnotherComponent />
  <MoreComponents />
  <BrowserRouter>
  ...
  </BrowserRouter>
</App>

我考虑过将 Header.js 制作为 HOC,但由于布局和样式原因,我无法将其嵌入到每个页面中。它需要位于 App.js 中完全相同的位置。

有什么想法/技术吗?

编辑:理想情况下,我希望每个页面都有 Header.js 的内容,就像 Helmet 包所做的那样:

<>
  {/* HomePage.js */}
  <HeaderPortal>
    <p>Content for the header</p>
  </HeaderPortal>

  <PageContent />
</>

最佳答案

实现此目的的一种方法是使用 React 的 context API,但是您必须在 DOM 中包装得相当高,以便能够从任何地方提供 header 内容的 setter 和 getter。

标题组件如下所示:

const HeaderContext = React.createContext();

// Provides the context and state - wrap app
export class HeaderProvider extends React.Component {
  state = {};
  render() {
    const { children } = this.props;
    return (
      <HeaderContext.Provider
        value={{
          header: this.state.header,
          setHeader: ({ header }) => this.setState({ header })
        }}
      >
        {children}
      </HeaderContext.Provider>
    );
  }
}
// Wrapper around WHERE the header will be rendered
export function HeaderPlacement() {
  return (
    <HeaderContext.Consumer>{({ header }) => header}</HeaderContext.Consumer>
  );
}
// Wrapper for setting the header CONTENT
export function HeaderPortal({ children }) {
  return (
    <HeaderContext.Consumer>
      {({ header, setHeader }) => 
        !header // Guard against setting the header in an endless loop
        && setHeader({ header: children })}
    </HeaderContext.Consumer>
  );
}

然后用法将如下所示:

function App() {
  return (
    <HeaderProvider>
      <div className="App">
        <HeaderPlacement />
        <Page />
      </div>
    </HeaderProvider>
  );
}

function Page() {
  return (
    <React.Fragment>
      <HeaderPortal><h1>Page A Test</h1></HeaderPortal>
      <div>
        Lorem ipsum dolor sit amet, consectetur adipiscing elit. In ex odio,
        eleifend in consequat nec, maximus lobortis ligula. Duis elementum, diam
        et imperdiet pulvinar, nulla ligula commodo elit, ac ullamcorper justo
        mauris quis velit. 
      </div>
    </React.Fragment>
  );
}

如果多个后代尝试设置 header 内容,您必须小心,因为您最终会遇到循环 setState 问题,或者一个会覆盖另一个。

这绝对不是唯一的方法,我避免使用钩子(Hook),但这肯定是 React-y 方法。

在此处查看代码和框:https://codesandbox.io/s/pj2q10700j

关于javascript - react : Change component's children from the outside,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54254273/

相关文章:

javascript - 使用javascript获取文件夹中的文件名

javascript - 无需重新加载 Controller 的子路由中的 UI-Router 和可选参数

javascript - React Router 无法正确路由

reactjs - 有人可以向我解释一下来自 ReactJS 的这段代码吗?

javascript - Flex 子元素在非常小的宽度上消失

javascript - 写一个 jQuery 选择器来过滤没有子类的子 div

javascript - Highcharts 中的 3 层圆环图

javascript - 如何使用 JavaScript 创建文档对象

javascript - 尝试使用 React 访问数组内的对象时出错

reactjs - token 过期后如何刷新 powerbi-client-react 组件?