声明性地更新组件内部的标记

时间:2018-11-11 18:25:02

标签: javascript reactjs

我的应用程序中有一个组件可以呈现一些数据,最常见的是页面标题。

标记

<Toolbar>
  <ToolbarRow>
    <div id="title-bar">
      {children}
    </div>
  </ToolbarRow>
</Toolbar>

我将如何声明性地更改内部数据?

我尝试过react-side-effects,这确实使我能够更改要渲染的标题,但后来我也希望能够添加组件。

组件不会存储在状态内部,因此……

然后我看了Portal,这些门户似乎正是我想要的,但是我得到了Target container is not a DOM element.

门户组件的标记

import React from "react";
import {createPortal} from 'react-dom'

const PageTitle = ({title, children}) => {
  return createPortal(
    <p>foo</p>,
    document.getElementById('title-bar')
  )
};

export default PageTitle;

我这样称呼门户组件:

<PageTitle title="Document Overview"/>

从上面的片段中可以看到,其他组件添加了<div id="title-bar" />,所以我想它与计时有关。

有人有个好主意吗?

1 个答案:

答案 0 :(得分:1)

我只是在这里将组件置于状态:

  const bars = [];

  export class TitleBar extends Component {
    state = { children: [] };

    componentDidMount() { bars.push(this); }
    componentWillUnmount() { bars.splice(bars.indexOf(this), 1); }
    render() { return this.state.children };
 }

 const RealPageTitle = ({ title }) => <div> { title } </div>;

 export class PageTitle extends Component {
   constructor(props) {
     super(props);
     this.real = RealPageTitle(props);
   }

   componentDidMount() {
     for(const bar of bars)
       bar.setState(({ children }) => ({ children: children.concat(this.real) }));
   }

   componentWillUnmount() {
     for(const bar of bars)
      bar.setState(({ children }) => ({ children: children.filter(child => child !== this.real) }));
   }

   render() { }
 }

这样,您只需在页面上的某处添加<PageTitle title={"Test"} />,它就会被添加到标题栏中。

我知道这并不遵循“最佳做法”,但确实可以实现