reactjs - 带有插槽的 React header 组件

标签 reactjs

我正在开发一个 React 应用程序,它有一些嵌套的 React 路由器开关和涉及根据当前显示的页面更改标题内容的非平凡逻辑。
我之前看到过这个问题的两种解决方案:

  • 一个 <Header/>它完全了解每条可能的路线和应用程序的状态
  • 平面页面布局:每个页面呈现自己的 <Header /> 实例

  • 在我看来,这两种解决方案都很糟糕。我认为标题必须被喂狗屎并保持在黑暗中。它所要做的就是停留在页面的顶部。受 React Helmet 的启发,我想为这个问题制定一个声明式的解决方案。
    假设我们有一个包含三个部分的标题:左、右和中心。在我们应用程序的根部,我们渲染类似
    return (
        <HeaderLeft>
            <Logo />
        </HeaderLeft>
        ...
    )
    
    正如预期的那样显示一个标志。
    在组件树层次结构的更深处,我们有一个 NestedPage这需要更改标题左侧部分中显示的内容。所以我们简单地做
    return (
        <HeaderLeft>
            <SomethingElse />
        </HeaderLeft>
        ...
    )
    
    诀窍是当我们离开 NestedPage 时我们需要放回 <HeaderLeft/>在我们来到 NestedPage 之前就在那里的东西.
    我想出了一个涉及 react 上下文和堆栈的 +/- 工作解决方案:
    https://codesandbox.io/s/great-mendeleev-0b5y4?file=/src/MainPage.js
    但是这个东西在很大程度上依赖于 useEffects 的执行顺序。
    问题
    有没有人有一个模式的惯用解决方案/想法/链接到如何实现所需的结果。

    最佳答案

    在浏览了 React Helmet 源代码后,我最终使用了 this little jewel
    它完全符合我的需要:从渲染顺序中的所有实例同步收集 Prop 。
    这样我们就可以得到最后的 children呈现:

    function reducePropsToState(props) {
      return props[props.length - 1];
    }
    
    棘手的部分是让 Header组件知道要渲染什么。幸运的是,我们都是软件工程师,React 运行在 javascript 上。
    我创建了一个简单的 observable 单例:
    class Observable {
      constructor() {
        this.value = null;
        this.subscribers = [];
        this.raf = null;
        this.notify = this.notify.bind(this);
      }
    
      subscribe(s) {
        this.subscribers.push(s);
        s(this.value);
      }
    
      setValue(c) {
        this.value = c || null;
        cancelAnimationFrame(this.raf);
        this.raf = requestAnimationFrame(this.notify);
      }
    
      notify() {
        this.subscribers.forEach((subscriber) => {
          subscriber(this.value);
        });
      }
    }
    
    在 header 组件中,我们订阅了这个 observable 并更新本地状态:
    useLayoutEffect(() => {
        contentObservable.subscribe((v) => {
          setContent(v);
        });
      }, []);
    
    Demo in codesandbox

    关于reactjs - 带有插槽的 React header 组件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65106545/

    相关文章:

    css - Tailwind 的 theme() 无法识别

    javascript - React 组件之间的通信

    javascript - 如何在 React Native 中对 Flatlist 数组中的单个项目进行动画处理

    javascript - 在 reactjs 应用程序中使用 dom-to-image 模块是否正确?

    javascript - react : Loop through array of strings

    reactjs - 调试 React propType 警告

    reactjs - 将 useEffect 与属性 react 为依赖项会导致无限循环

    reactjs - 有没有办法让 React 子组件显示为字符串,带有缩进、回车和 jsx 语法糖?

    javascript - Webpack-dev-server 在 HTML 页面中注入(inject)包,但没有渲染任何内容

    css - 如何修改 reactjs-dropdown-component 的 css?