MCPcopy
hub / github.com/lit/lit / useController

Function useController

packages/react/src/use-controller.ts:114–190  ·  view source on GitHub ↗
(
  React: typeof window.React,
  createController: (host: ReactiveControllerHost) => C
)

Source from the content-addressed store, hash-verified

112 * create function is only called once per component.
113 */
114export const useController = <C extends ReactiveController>(
115 React: typeof window.React,
116 createController: (host: ReactiveControllerHost) => C
117): C => {
118 const {useState, useLayoutEffect} = React;
119
120 // State to force updates of the React component
121 const [kickCount, kick] = useState(0);
122
123 // Create and store the controller instance. We use useState() instead of
124 // useMemo() because React does not guarantee that it will preserve values
125 // created with useMemo().
126 // TODO (justinfagnani): since this controller are mutable, this may cause
127 // issues such as "shearing" with React concurrent mode. The solution there
128 // will likely be to snapshot the controller state with something like
129 // `useMutableSource`:
130 // https://github.com/reactjs/rfcs/blob/master/text/0147-use-mutable-source.md
131 // We can address this when React's concurrent mode is closer to shipping.
132
133 let shouldDisconnect = false;
134 const [host] = useState(() => {
135 const host = new ReactControllerHost<C>(kickCount, kick);
136 const controller = createController(host);
137 host._primaryController = controller;
138 // Note, calls to `useState` are expected to produce no side effects and in
139 // StrictMode this is enforced by not running effects for the first render.
140 //
141 // This happens in StrictMode:
142 // 1. Throw away render: component function runs but does not call effects
143 // 2. Real render: component function runs and *does* call effects,
144 // 2.a. if first render, run effects and
145 // 2.a.1 mount,
146 // 2.a.2 unmount,
147 // 2.a.3 remount
148 // 2b. if not first render, just run effects
149 //
150 // To preserve update lifecycle ordering and run it before this hook
151 // returns, run connected here but schedule and async disconnect (handles
152 // lifecycle balance for `(1) Throw away render`).
153 // The disconnect is cancelled if the effects actually run (handles
154 // `(2.a.1) Real render, mount`).
155 host._connected();
156 shouldDisconnect = true;
157 microtask.then(() => {
158 if (shouldDisconnect) {
159 host._disconnected();
160 }
161 });
162 return host;
163 });
164
165 host._updatePending = true;
166
167 // This effect runs only on mount/unmount of the component (via the empty
168 // deps array). If the controller has just been created, it's scheduled
169 // a disconnect so that it behaves correctly in StrictMode (see above).
170 // The returned callback here disconnects the host when the component is
171 // unmounted (handles `(2.a.2) Real render, unmount` above).

Callers 2

useTestFunction · 0.85
useTestFunction · 0.85

Calls 4

_connectedMethod · 0.95
_disconnectedMethod · 0.95
_updatedMethod · 0.95
_updateMethod · 0.95

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…