Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does React provide independent contexts for subtrees?

Tags:

reactjs

jsx

If, as a thought experiment, I were to write my own createElement implementation for JSX, what might support for implicit context look like?

In particular, I can't figure out how with the limited means of JSX's createElement signature, contexts can be independent for different subtrees. (It appears React's Context handling has become more elaborate in recent versions; I'm mostly interested in the seemingly more straightforward mechanisms of earlier versions.)

This might be used to automatically determine heading levels, for example:

<Section title="Hello World">
    <Card title="Details" />
</Section>
<Card title="Example" />

Here Card would automatically generate <h3> and <h2>, respectively, by relying on something like context.headingLevel.

like image 267
AnC Avatar asked Feb 07 '21 10:02

AnC


People also ask

How do React contexts work?

What is context in React? React's context allows you to share information to any component, by storing it in a central place and allowing access to any component that requests it (usually you are only able to pass data from parent to child via props).

What is React context Good For?

React context allows us to pass down and use (consume) data in whatever component we need in our React app without using props. In other words, React context allows us to share data (state) across our components more easily.

Does react native support context?

React Context API provides a easy way to pass data through the component tree without having to pass props down manually at every level. You can find more about the Context API in React documentation. You can use the React Context API with React Native Navigation with a limitation.


1 Answers

A very nice question, that shows how different is the concept of creating React Elements to actually executing the render functions (either the .render method of class components or simply the main body of a functional component).

In JSX itself (which is just React.createElement(…)) there‘s no concept of “context” at all. It comes into existance only when the components are rendered. It is indeed a duty of the React Renderer (such as React DOM or React Native) to actually implement Context APIs.

If you remove the ability to store states and to update the UI you are left with a minimal React implementation that only “renders once”, but perfectly fine to understand the problem at hand.

Everytime the React Renderer needs to render a React Elements tree (such as one built with JSX) it passes every single element and transforms it into a DOM structure, but when it encounters a component node (not a “native” element) it needs to render it to obtain its React Element sub tree, and swap the original node with it.

It’s in this specific moment that React can keep track of which Context values to pass to which components, since it is traversing the tree.

So, to answer directly your question, you can’t implement context in the “element creation phase”, inside your JSX implementation, you need to do it in a subsequent phase when you can traverse the tree.

If you were trying to build an “immediate JSX” you probably have something like this:

function createElement(type, props, ...children) {
  props = { children, ...props };

  if (typeof type === 'function') {
    return type(props);
  } else {
    return { type, props };
  }
}

In thise case you will not be able to implement an API similar to context, because the execution order is inner-then-outer:

const div = createElement('div', {}, createElement(Card, {}));
// identical to
const card = createElement(Card, {}); // inner, and then…
const div = createElement('div', {}, card); // outer
like image 117
Pier Paolo Ramon Avatar answered Sep 18 '22 19:09

Pier Paolo Ramon