Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
313 views
in Technique[技术] by (71.8m points)

javascript - React Hooks - What's happening under the hood?

I've been trying out React Hooks and they do seem to simplify things like storing state. However, they seem to do a lot of things by magic and I can't find a good article about how they actually work.

The first thing that seems to be magic is how calling a function like useState() causes a re-render of your functional component each time you call the setXXX method it returns?

How does something like useEffect() fake a componentDidMount when functional components don't even have the ability to run code on Mount/Unmount?

How does useContext() actually get access to the context and how does it even know which component is calling it?

And that doesn't even begin to cover all of the 3rd party hooks that are already springing up like useDataLoader which allows you to use the following...

const { data, error, loading, retry } = useDataLoader(getData, id)

How do data, error, loading and retry re-render your component when they change?

Sorry, lots of questions but I guess most of them can be summed up in one question, which is:

How does the function behind the hook actually get access to the functional/stateless component that is calling it so that it can remember things between re-renders and initiate a re-render with new data?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

React hook makes use of hidden state of a component, it's stored inside a fiber, a fiber is an entity that corresponds to component instance (in a broader sense, because functional components don't create instances as class components).

It's React renderer that gives a hook the access to respective context, state, etc. and incidentally, it's React renderer that calls component function. So it can associate component instance with hook functions that are called inside of component function.

This snippet explains how it works:

let currentlyRenderedCompInstance;
const compStates = new Map(); // maps component instances to their states
const compInstances = new Map(); // maps component functions to instances

function useState(initialState) {
  if (!compStates.has(currentlyRenderedCompInstance))
    compStates.set(currentlyRenderedCompInstance, initialState);

  return [
    compStates.get(currentlyRenderedCompInstance) // state
    val => compStates.set(currentlyRenderedCompInstance, val) // state setter
  ];
}

function render(comp, props) {
  const compInstanceToken = Symbol('Renderer token for ' + comp.name);

  if (!compInstances.has(comp))
    compInstances.set(comp, new Set());

  compInstances.get(comp).add(compInstanceToken);

  currentlyRenderedCompInstance = compInstanceToken;

  return { 
    instance: compInstanceToken,
    children: comp(props)
  };
}

Similarly to how useState can access currently rendered component instance token through currentlyRenderedCompInstance, other built-in hooks can do this as well and maintain state for this component instance.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...