React 16 的 Portal API 是要取代 Context API 吗?

Is React 16's Portal API meant to replace the Context API?

我注意到新功能 portals 做同样的事情但更好?我不太了解门户,但它似乎是管理嵌套组件更新的新方法? 我知道 Reacts Context API 是实验性的,并注意到 componentDidUpdate 不再收到 prevContext,他们放弃了 contextTypes

我还注意到他们正在引入 React 16's Portal API,但不确定这是否旨在取代 Context API。

所以再说一遍,如上所述,React 16 的 Portal API 是否意味着要替换 Context API?

编辑:借用这个话题,conext 是在 React 中管理 i18n 本地化的最佳方式吗?

TL;DR => PortalsContext解决不同的目的,一个是在任意层级注入DOM,另一个是在任何级别注入道具。 Context 可以模仿 PortalsPortals 目前不能模仿 Context 至少在不引入代码气味的情况下是这样。

注意:以下是基于我对这两个概念的理解,如果有人对此有进一步的想法或更正,请随时编辑答案。

据我所知,Portals 顾名思义,是一种让您渲染不需要位于组件树层次结构中的组件的途径。这对于 ModalsPopovers 或任何需要在树中的特定位置缝合的组件非常有效。

Context 是为了与各种兄弟和子组件进行通信,而不必从父组件一直向下传递 props 到预期的组件。当然,这是一个重要的特性,但它仍处于实验阶段,可能是因为这可以通过 event-emittersReduxMobX 实现集中状态管理.

我假设您 i18n 的用例需要跨组件进行大量通信,您可能想查看这篇很棒的文章

COMPONENT COMMUNICATION

Portals 和 Context 有助于实现这种通信,但存在差异。 Portals 可以在任何级别渲染或注入 DOM,而 Context 可以在子组件树的任何级别注入道具。

您总是可以使用 Context 实现 Portals 能够做到的事情,但我认为 Portals 无法模仿 Context 的功能。

EG: 可以做类似的事情来模仿 Portals 使用 Context 所做的事情。在 Portals AFAIK 中,您只能发送 DOM 个节点 ReactDOM.createPortal(child, container)。可能有一种方法可以实现该功能,但这肯定会导致代码异味。

class Parent extends React.Component {

    getChildContext() {
        return {
            renderModal: this.renderModal
        }
    }

    renderModal = (children) => {
        this.setState({
            open: !this.state.open,
            injectableChildren: children
        })
    }

    render() {
        this.state.open
            ?
            <div>
                {this.state.injectableChildren}
            </div>
            : 
            null
        // JSX
    }
}


class SomeSibling extends React.Component {
    static contextTypes = {
       renderModal: React.PropTypes.func
    }

    handleOnClick = (event) => {
        this.context.renderModal(renderableChildJSX);
    }

    renderableChildJSX = () => (
        <div>
            YAY I AM GETTING RENDERED AT THE ROOT
        </div>
    )

    render() {
        return(
            <div onClick={this.handleOnClick}>
            </div>
        )
    }
}

就我而言,我害怕使用 Context 尽管它很灵活,因为 React 文档总是提到它是一个实验性功能,并反复警告不要完全使用此功能。我的猜测是 React 正在考虑稳定此功能或将其完全从 React 代码库中删除,这是一个双向的风险。

结论: IMO,Portals 在当前状态下,它试图解决的问题与 Context 的构建目的完全不同,最好使用 event-emitters,唯一的原因是 Context 可能会被弃用。

门户 API 不同于上下文 API、

Portals provide a first-class way to render children into a DOM node that exists outside the DOM hierarchy of the parent component.

当您可能想要呈现模态框或弹出框时,门户很有用,它们需要在当前 DOM 层次结构之外才能具有适当的 z 索引。大多数情况下,您会直接在顶层渲染它们。但是,使用 Portal,您可以在任何层级呈现 DOM 元素。

React 16中,可以像

一样创建门户
ReactDOM.createPortal(child, container)
另一方面,

Context 用于将数据传递到不同的组件,而无需在每个级别向下传递。您可能有不同级别的组件,其中一些可能非常嵌套,并且在每个级别一直向下传递 props 可能不是一个很好的解决方案,并且它会带来显着的性能障碍,因为很多更高级别实际上可能不是使用这些道具,但仍会重新渲染此类道具更改。

从 v16.3.0 开始,React 引入了一个新的 context API 上下文不再是实验性的。

Context is designed to share data that can be considered “global” for a tree of React components, such as the current authenticated user, theme, or preferred language. Using context, we can avoid passing props through intermediate elements. but it shouldn't be used to just pass props a few levels down

一般来说,你会使用像

这样的上下文
export const MyContext = React.createContext();

class Provider extends React.Component {
   state = {
       theme: 'dark'
   }
   handleChange=() => {}

   render() {
        return <MyContext.Provider 
           value={{state: this.state, handleChange: this.handleChange}}
           >
               {this.props.children}
           </MyContext.Provider?>
   }
}

对于要使用上下文值的组件,您可以编写

import {MyContext} from 'path/to/context'
...
render() {
    return <MyContext.Consumer>
         {(theme) => <div>{theme}</div>}
     </MyContext.Consumer>
}

To piggyback on this topic, is context the best way to manage i18n localisation in react?

是的,i18n 本地化是使用上下文的一个很好的用例,因为您需要在整个应用程序中传递 language/paramerisation 选择。如果您需要与 APIs 进行更多集成以进行本地化,您可以考虑使用 Redux。

有关详细信息,请查看

上的此答案