在2个React DOM之间传递数据

har*_*ksa 6 javascript reactjs redux react-dom

在一个网站中,我有多个反应渲染元素.我想在这两个单独的元素之间传递数据.在两个元素之间传递数据的可能选项有哪些

ReactDOM.render(<Header/>, document.getElementById('header'));
ReactDOM.render(<SideBar/>, document.getElementById('sidebar'));
Run Code Online (Sandbox Code Playgroud)

我希望在这些元素之间存储单个数据.就像我在一个组件中获取数据一样,我希望所有元素都可以访问这些数据(在所有ReactDOM中).那么可能的选择是什么呢?

编辑:由于要求我无法将它们合并到同一个根组件中.只有页面的某些部分处于反应中,其他部分仍在HTML/Jquery中.所以我在所需的div中单独渲染它们.

redux存储在不同的ReactDOM之间工作吗?

tri*_*ixn 10

使用门户react-dom库:

Portals 提供了一种一流的方式来将子组件渲染到存在于父组件的 DOM 层次结构之外的 DOM 节点中。


const HeaderPortal = ReactDOM.createPortal(<Header />, document.getElementById('header'))
const SideBarPortal = ReactDOM.createPortal(<SideBar />, document.getElementById('sidebar'))

const store = createStore(/* ... */)

ReactDOM.render(
  <YourDataStoreProvider store={store}>
    <HeaderPortal />
    <SideBarPortal />
  </YourDataStoreProvider>, 
  document.getElementById('root') // assuming you have an empty "dummy" node with that id
);
Run Code Online (Sandbox Code Playgroud)

只需将您的应用程序渲染到 DOM 中任何位置的容器中,或者创建一个新的“虚拟”节点。在我的示例中,我假设有一个带有 id 的空节点root。然后将您的其他组件渲染到门户中。

redux 存储在不同的 ReactDOM 之间工作吗?

您的应用程序将像完全呈现在同一个容器中一样工作。如果您使用 Portal,您的组件将位于具有相同上下文的同一组件树中,同时在其他地方呈现。

我应该使用门户网站吗?

使用 Portals 通常旨在用于在视觉上需要“突破”其容器(如模态或对话框)的组件。但是您也可以使用它们来创建可以在任何地方呈现的类似小部件的组件。

创建通用 Portal 组件

您还可以创建一个通用<Portal>组件来创建一个给定容器的门户id

import {createPortal} from 'react-dom';

const Portal = ({children, container}) => createPortal(
    children,
    document.getElementById(container),
);

export default Portal;
Run Code Online (Sandbox Code Playgroud)

并以这种方式使用它:

ReactDOM.render(
  <YourDataStoreProvider store={store}>
    <Portal container="header">
      <Header />
    </Portal>
    <Portal container="sidebar">
      <SideBar />
    </Portal>
  </YourDataStoreProvider>, 
  document.getElementById('root')
);
Run Code Online (Sandbox Code Playgroud)

编辑

你需要在 DOM 中有一个节点,你可以在其中渲染你的应用程序。这可以是您创建的新 DOM 元素,也可以是您已有的容器之一。如果您使用<Portal>上面的组件,它也可能如下所示:

ReactDOM.render(
    <YourDataStoreProvider store={store}>
        <Header /> // this will be visible in your header container
        <Portal container="sidebar">
            <SideBar /> // this will be rendered to the sidebar container
        </Portal>
    </YourDataStoreProvider>, 
    document.getElementById('header')
);
Run Code Online (Sandbox Code Playgroud)

这将在header容器中呈现您的应用程序。但是只有您的<Header>组件在该容器中才会真正具有 DOM 表示。侧边栏将由sidebar门户呈现在容器中。但是它们仍然会共享相同的 React 组件树并具有相同的存储提供程序。


Tom*_*bot 5

您可以创建一个组件容器,并将它们作为子项并将它们分开.通过道具和母容器交换数据.

我举一个例子:

https://codepen.io/hkares/pen/rvLPzQ

HTML

//html
<header id="header"></header>
<main>
  <nav id="nav"></nav>
  <section>I am section</section>
</main>
<footer>This is a footer</footer>
<div id="useless"></div>
Run Code Online (Sandbox Code Playgroud)

Index.js

const HEADER_NODE = document.querySelector("#header");
const NAVBAR_NODE = document.querySelector("#nav");

const Header = ({ name }) => ReactDOM.createPortal(<h1>{name}</h1>, HEADER_NODE);

const NavBar = (props) => ReactDOM.createPortal(
  <article>
    <label>
      Set header name: <input {...props} />
    </label>
  </article>
, NAVBAR_NODE);

class Container extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      value: "this is a header"
    };
  }

  onChange = ({ target }) => this.setState({ value: target.value });

  render() {
    const { value } = this.state;
    return (
      <React.Fragment>
        <Header name={value} />
        <NavBar value={value} onChange={this.onChange} />
      </React.Fragment>
    );
  }
}

ReactDOM.render(
  <Container />,
  document.querySelector("#useless")
);
Run Code Online (Sandbox Code Playgroud)