最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Is React 16's Portal API meant to replace the Context API? - Stack Overflow

programmeradmin2浏览0评论

I noticed new feature portals do the same thing but better? I dont know much about portals but it seems to be the new way to manage nested ponent updates? I knew Reacts Context API was experimental, and noticed ponentDidUpdate no longer receives prevContext and they dropped contextTypes.

I also noticed they are introducing React 16's Portal API and not sure if this is intended to replace the Context API.

So again, as mentioned above, is React 16's Portal API meant to replace the Context API?

EDIT: To piggyback on this topic, is conext the best way to manage i18n localization in react?

I noticed new feature portals do the same thing but better? I dont know much about portals but it seems to be the new way to manage nested ponent updates? I knew Reacts Context API was experimental, and noticed ponentDidUpdate no longer receives prevContext and they dropped contextTypes.

I also noticed they are introducing React 16's Portal API and not sure if this is intended to replace the Context API.

So again, as mentioned above, is React 16's Portal API meant to replace the Context API?

EDIT: To piggyback on this topic, is conext the best way to manage i18n localization in react?

Share edited Jun 25, 2018 at 7:52 Brian Tompsett - 汤莱恩 5,89372 gold badges61 silver badges133 bronze badges asked Dec 11, 2017 at 2:56 garrettmacgarrettmac 8,5953 gold badges44 silver badges61 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 6

TL;DR => Portals and Context solve different purposes, one is to inject DOM at any level and other is to inject props at any level. Context can mimic Portals but Portals AS OF NOW cannot mimic Context not at least without introducing code smell.

NOTE: Below is based on my understanding of the two concepts, if anyone has further thoughts or corrections on this please feel free to edit the answer.

From what I was able to understand Portals are, as the name suggests, a door way for you to render ponents that need not be in the ponent tree hierarchy. This works like perfectly for Modals, Popovers or any ponent which needs to be stitched at a particular location in the tree.

Context is to municate with various sibling and child ponents without having to pass props all the way down from parent to the intended ponent. Of course, this is an important feature to have but it remained in the experimental phase probably due to the fact that this can be achieved by event-emitters and Redux, MobX for a centralized state management.

I am assuming that your use case for i18n would require a lot of munication across ponents for which you might want to look at this great article

COMPONENT COMMUNICATION

Portals and Context help achieving this kind of munication but there is a difference. Portals can render or inject DOM at any level and Context can inject props at any level in the subponent tree.

You can always achieve what Portals are able to do using Context but I don't think Portals can mimic Context functionality.

EG: Something like this can be done to mimic what Portals do using Context. Where as in Portals AFAIK you can only send DOM Nodes ReactDOM.createPortal(child, container). May be there is a way to achieve the functionality but that would surely lead to code smell.

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>
        )
    }
}

In my case, I feared from using Context despite it's flexibility due to the fact that React docs always mentioned that it's an experimental feature and warned repeatedly from using this feature full-blown. My guess is that React is looking at stabilising this feature or pletely scrape it off the React codebase which is a risk that could go both ways.

CONCLUSION: IMO, Portals in it's current state and the problem it is trying to resolve is entirely different from what Context is built for and it is better to use event-emitters with the only reason that Context might possibly be deprecated.

A Portal API is different from a Context API,

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

A portal is useful when you might want to render Modals or Popovers, that need to be outside of the current DOM hierarchy in order for it to have proper z-indexes. Most often you would render these in the top level directly. However with Portal you can render DOM element at any level of hierarchy.

In React 16, portals can be created like

ReactDOM.createPortal(child, container)

Context on the other hand is used to pass the data onto different ponent without the need to pass if down at each level. You may have ponents at different level, some of which may be extremely nested and passing the props down all the way at each level might not be a great solution and it es with significant performance hindrance, since a lot the higher levels may not actually be using these props but will still re-render on such prop changes.

From v16.3.0 React has introduced a new context API and context is no longer experimental.

Context is designed to share data that can be considered “global” for a tree of React ponents, 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

In general you would use context like

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?>
   }
}

and for the Component you want to use context value, you would write

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?

Yes i18n localisation is a good usecase for using context since you would need to pass on language/paramerisation selection throughout your app. In cases where you need much more integration with APIs to do localisation, you can think about using Redux.

For more details check this answer on whether to use Context or Redux

发布评论

评论列表(0)

  1. 暂无评论