Coder Social home page Coder Social logo

dai-shi / use-context-selector Goto Github PK

View Code? Open in Web Editor NEW
2.5K 12.0 56.0 2.32 MB

React useContextSelector hook in userland

Home Page: https://www.npmjs.com/package/use-context-selector

License: MIT License

JavaScript 4.74% TypeScript 95.26%
react react-hooks react-context custom-hook

use-context-selector's Introduction

use-context-selector

CI npm size discord

React useContextSelector hook in userland

Introduction

React Context and useContext is often used to avoid prop drilling, however it's known that there's a performance issue. When a context value is changed, all components that useContext will re-render.

To solve this issue, useContextSelector is proposed and later proposed Speculative Mode with context selector support. This library provides the API in userland.

Prior to v1.3, it uses changedBits=0 feature to stop propagation, v1.3 no longer depends on this undocumented feature.

Install

This package requires some peer dependencies, which you need to install by yourself.

npm install use-context-selector react scheduler

Notes for library authors:

Please do not forget to keep "peerDependencies" and note instructions to let users to install peer dependencies.

Technical memo

To make it work like original React context, it uses useReducer cheat mode intentionally.

It also requires useContextUpdate to behave better in concurrent rendering. Its usage is optional and only required if the default behavior is unexpected.

If you need a simpler solution, you can use useSyncExternalStore without any libraries. See an example.

Usage

import { useState } from 'react';
import { createRoot } from 'react-dom/client';

import { createContext, useContextSelector } from 'use-context-selector';

const context = createContext(null);

const Counter1 = () => {
  const count1 = useContextSelector(context, (v) => v[0].count1);
  const setState = useContextSelector(context, (v) => v[1]);
  const increment = () =>
    setState((s) => ({
      ...s,
      count1: s.count1 + 1,
    }));
  return (
    <div>
      <span>Count1: {count1}</span>
      <button type="button" onClick={increment}>
        +1
      </button>
      {Math.random()}
    </div>
  );
};

const Counter2 = () => {
  const count2 = useContextSelector(context, (v) => v[0].count2);
  const setState = useContextSelector(context, (v) => v[1]);
  const increment = () =>
    setState((s) => ({
      ...s,
      count2: s.count2 + 1,
    }));
  return (
    <div>
      <span>Count2: {count2}</span>
      <button type="button" onClick={increment}>
        +1
      </button>
      {Math.random()}
    </div>
  );
};

const StateProvider = ({ children }) => (
  <context.Provider value={useState({ count1: 0, count2: 0 })}>
    {children}
  </context.Provider>
);

const App = () => (
  <StateProvider>
    <Counter1 />
    <Counter2 />
  </StateProvider>
);

createRoot(document.getElementById('app')).render(<App />);

API

createContext

This creates a special context for useContextSelector.

Parameters

  • defaultValue Value

Examples

import { createContext } from 'use-context-selector';

const PersonContext = createContext({ firstName: '', familyName: '' });

useContextSelector

This hook returns context selected value by selector.

It will only accept context created by createContext. It will trigger re-render if only the selected value is referentially changed.

The selector should return referentially equal result for same input for better performance.

Parameters

  • context Context<Value>
  • selector function (value: Value): Selected

Examples

import { useContextSelector } from 'use-context-selector';

const firstName = useContextSelector(PersonContext, (state) => state.firstName);

useContext

This hook returns the entire context value. Use this instead of React.useContext for consistent behavior.

Parameters

  • context Context<Value>

Examples

import { useContext } from 'use-context-selector';

const person = useContext(PersonContext);

useContextUpdate

This hook returns an update function to wrap an updating function

Use this for a function that will change a value in concurrent rendering in React 18. Otherwise, there's no need to use this hook.

Parameters

  • context Context<Value>

Examples

import { useContextUpdate } from 'use-context-selector';

const update = useContextUpdate();

// Wrap set state function
update(() => setState(...));

// Experimental suspense mode
update(() => setState(...), { suspense: true });

BridgeProvider

This is a Provider component for bridging multiple react roots

Parameters

  • $0 {context: Context<any>, value: any, children: ReactNode}

    • $0.context
    • $0.value
    • $0.children

Examples

const valueToBridge = useBridgeValue(PersonContext);
return (
  <Renderer>
    <BridgeProvider context={PersonContext} value={valueToBridge}>
      {children}
    </BridgeProvider>
  </Renderer>
);

useBridgeValue

This hook return a value for BridgeProvider

Parameters

  • context Context<any>

Limitations

  • In order to stop propagation, children of a context provider has to be either created outside of the provider or memoized with React.memo.
  • Provider trigger re-renders only if the context value is referentially changed.
  • Neither context consumers or class components are supported.
  • The stale props issue can't be solved in userland.
  • Tearing is only avoided if all consumers get data using useContextSelector. If you use both props and use-context-selector to pass the same data, they may provide inconsistence data for a brief moment. (02_tearing_spec fails)

Examples

The examples folder contains working examples. You can run one of them with

PORT=8080 pnpm run examples:01_counter

and open http://localhost:8080 in your web browser.

You can also try them directly: 01 02 03

Projects that use use-context-selector

use-context-selector's People

Contributors

aslemammad avatar csr632 avatar dai-shi avatar dependabot[bot] avatar jovidecroock avatar kylemcd avatar morijenab avatar shalldie avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

use-context-selector's Issues

[Question] Getting several context values at once?

Hi 👋

First things first, thx a lot for this great work! 👏 I'm still discovering it, and maybe I'm going to ask a silly question but... is there any reason why useContextSelector examples were always using the same "one call, one value" pattern:

const v1 = useContextSelector((ctx) => ctx.v1)
const v2 = useContextSelector((ctx) => ctx.v2)
const v3 = useContextSelector((ctx) => ctx.v3)
...

...which seems quite verbose to me. Couldn't we simply use a single call such as:

const { v1, v2, v3 } = useContextSelector(({ v1, v2, v3 }) => ({ v1, v2, v3 }))

Thx a lot for your answer! 🙏

Shallow check in object/array destructuring.

Zustand has shallow as the second argument to optimize for referential equality.

Is it possible to do something like that with this library?

  const sdkReader = useSDK((s) => s.sdkReader)
  const sdkWriter = useSDK((s) => s.sdkWriter)

Can we write this in one line with destructuring ?

Using use-context-selector in _app.tsx return undefined (Next.js)

So, I have been building an app with next.js and just ran into a minor problem

when calling either useContext or useContextSelector in _app.tsx the return is always undefined

"next": "latest"
"react": "^17.0.2",
"use-context-selector": "^1.3.9",
"scheduler": "^0.20.2",

is this expected behaviour?

Support for custom equality function

It seems like the library is currently hardcoded to compare the value produced by the selector using Object.is

|| Object.is(ref.current.s, ref.current.f(nextValue))) {

Sometimes it may be useful to use a different equality comparison such as shallow equal when composing an object. The redux useSelector API has an extra optional parameter for this purpose, which can be used like

const selectedData = useSelector(selectorReturningObject, shallowEqual)

Would you consider supporting this in use-context-selector?

How does selector memoization work?

The RFC proposes that both the context and the selector are memoized.

However, it seems like this library works differently. E.g.:

  const count1 = useContextSelector(context, v => v[0].count1);

From my understanding of the RFC, this should defeat the memorization and make useContextSelector ineffective as a performance optimization.

Obviously, the above snippet works for this library, so could you please explain how? Is the selector memoized, and if so, how?

To cite a more complex example, let's look at this snippet:

function Foo({ id }) {
  const value: number = useContextSelector(Context, c => c.values[id])
  return <>{id} = {value}</>
}

How will this behave if both Context and id may change? (If props are too constant, then id may also be state.)

Stale props issue

Hei brother,
Thanks for this awesome lib !

When you have the time, could you please look over this piece of code and confirm that this is the correct way of reproducing the stale props late revalidation issue ?
https://codesandbox.io/s/usecontextselector-late-state-update-lopcv

I've been having some troubles with late updates in my app and only found out about this after carefully debugging parts of my app that contained memoized data parts provided by use-context-selector.
In case that's true, for use cases where instant re-validation is needed, would you recommend simply using react's context instead and NOT use-context-selector ?

Thanks !

Usage

Hello Daishi,

Here is how I integrated this lib into an example.
What do you think about these patterns?
Maybe you would like to integrate the utils into the lib or into another lib?

It is typed state, so typing 'state.' will suggest the state properties.

There is also performance test. Click on the button in the ui. There are 3 columns. Open the React-Perf and click on forceUpdate.
It can be seen that with this context the update takes 3ms, with root update (every component rerendered) it takes 70ms and same memoized 35ms.

Then I want to experiment with how to construct the state in this hook of context provider. Thinking towards useReducer and will experiment with your useAsyncReducer.

Also you can see there contextStoreM, it is implementation with
https://github.com/mohebifar/react-use-context-selector
Btw it is slower than yours.

May I ask a question.
I am 3 years into React/Mobx/Redux (used also easy-peasy). Read btw your discussion in gqless about mutable/immutable. Also have seen that you use proxy to track state usage.
The question is - what is the actual reason to manage immutable store, other than time travel ?
The question arose when it was easier for me to put an array with other methods into useRef, mutate it in the methods and just call 'forceUpdate'. It worked. So what is the reason to manage immutability ?
Thanks.

Is lib behavior correct?

Testing with example1, I noticed that when I switch from incremental click action to text switch it causes a re-rendering of the previous element. Is this behavior correct?

tests

how to stop re-rendering with React.memo?

Hi,
React.memo has a comparator parameter which can stop a component from re-rendering, but it automatically receives only the props.

If we have context with context selector which creates a binding to that property, how can we use React.memo or something else to prevent a re-render?

I have a situation in which I have a parent with a grid, and it needs to track where the focus is on the children. So I need the index in the parent, but I don't want the change of index to cause a re-render. If save the focus index in the context and bind that field in the parent, it causes all the children to re-render which makes the performance very bad...

Trigger the rendering of the component twice in a certain scenario

DAISHI さん、こんにちは.
僕はプロジェクトで”use-context-selector”を使いましたが、下のような demo で、子のコンポーネントが二回をトリガーされました.

demo:https://codesandbox.io/s/billowing-breeze-em4lk?file=/src/App.tsx
再現方法:1. コンソールを開く、2. に文字を入力します
現象:Child のコンポーネントが二回をトリガーされました

上記の demo では、react によって提供される "context" を使うと、子のコンポーネントは1回だけトリガーされました.
僕は react の更新がバッチ処理されない原因となるコードがあるかどうかを推測しています.
ありがとう.

Possible to miss update?

If an update happens before useIsomorphicLayoutEffect is triggered, where listener is added, the dispatch of consumer will not be called(because listener has not been added yet). And it will stay at the old state forever.

More complex examples or good/bad practices documented

Hey! Awesome work! I hope it's gonna be a part of React 🤞.

To be precise: I'm not raising issue, rather feature request - could you please extend documentation or add more complex examples? Especially part about good/bad practices. For example how to access function/objects stored in context because those must have same reference in order to skip update.
Example - component is getting function from context:

const addListener = useContextSelector(
    ListenerContext,
    listeners => listeners.addListener
)

Provider looks like:

const [listeners, setListeners] = useState([])
const [state, setState] = useState({}) // some other state
const addListener = (listener) => {
    // some complex logic 
    setListeners(newListeners)
}

const state = {
    state,
    addListener,
}

return (
    <Provider value={state}>
        {children}
    </Provider>
)

Therefore as compare condition is:

(ref.current.v === nextValue || Object.is(ref.current.s, ref.current.f(nextValue)))

Update will be triggered. However it might be fixed by useRef:

const { current: addListener } = useRef((listener) => {
    // some complex logic 
    setListener(newListeners)
})

I think there are more examples of how to use/how to not use this hook and it might be helpful to document it.

Cheers!

Can we destructuring useContextSelector?

I avoid it will not optimize performance or re-render. So, Can I destructuring useContextSelector or not. thanks you

const { loadingLogOut, loadingUserProfile } = useContextSelector(ctxAuth, (v) => v[0]);

Discussion: adding a `createProviderFromHook` utility

I absolutely love this library, and am using it in several big projects. So let me start with a thank you!
I wanted to suggest a small feature. I am more than happy to create a PR, but wanted to discuss it first.

The problem: boilerplate

When working with Context (both the native React context and the Context of this library), especially with hooks, I find myself repeating this same exact boilerplate:

  1. Create a context
  2. Export a custom Provider that wraps context.Provider
  3. Export a custom hook that wraps useContext/useContextSelector but throws if the Provider is missing
  4. Create a type definition for the context's value

For example, here's the boilerplate required for this repo's Usage example:

const MISSING_PROVIDER = Symbol('MISSING_PROVIDER');
const context = createContext<CounterInfo>(MISSING_PROVIDER);

type CounterInfo = [ { count1: number, count2: number }, setState: any ];

export const CounterProvider = ({ children }) => (
  <context.Provider value={useState({ count1: 0, count2: 0 })}>
    {children}
  </context.Provider>
);

export const useCounterSelector = (selector: any) => {
  return useContextSelector(context, (value) => {
    if (value === MISSING_PROVIDER) throw new Error("Missing `CounterProvider`");
    return selector(value);
  });
};

The solution: createProviderFromHook

All of this boilerplate can be eliminated! Implementation details aside, here's the finished result:

export const [ CounterProvider, useCounterSelector ] = createProviderFromHook(() => useState({ count1: 0, count2: 0 }));

This syntax is inspired by the wonderful constate library,.

A few noteworthy things about this createProviderFromHook function:

  1. The raw context is kept private, so you don't have to remember to import createContext from the right place
  2. The custom Provider boilerplate is eliminated.
  3. The custom useCounterSelector boilerplate is eliminated, and automatically checks for missing providers.
  4. Strongly typed! All type arguments are correctly inferred, no manual type defs needed.

Let me know what you think about adding this utility. The implementation would not be big or cause bloat, and this feature would be extremely useful to anyone using this library.

How do you subscribe to entire context to replicate React.useContext?

Your example code shows how to subscribe to context variables
e.g.

const Counter2 = () => {
  const count2 = useContextSelector(context, v => v[0].count2);
  const setState = useContextSelector(context, v => v[1]);

How do I subscribe to the entire context using useContextSelector if i initialise my context with your CreateContext method?

React's useContext doesnt work if i use your createContext method to initialise context and I cant find documentation/code to subscribe to everything on the context and not just individual properties or state slices.

Thanks

Jest cannot find module react-dom

image

If more info needed, let me know.

I'm using react native 0.63.3 and use-context-selector ^1.3.7.

edit
I guess it's happening because use-context-selector is trying to import from index.umd.js instead index.native.umd.js.

I'm wondering if it's really caused by use-context-selector or jest. But how can I fix it? Anyone already passthrough it?

performance testing?

Hi,
this package is very clean and I'd very much like to use it. Have you done performance testing on it?

"useContextSelector requires special context" warning is never printed

This code is intended to print a warning if you use createContext from react rather than use-context-selector. I made this mistake and the warning was not printed. This happens because typeof process is expected to be 'undefined' when running in the browser. Going to submit a PR for this.

if (typeof process === 'object' && process.env.NODE_ENV !== 'production') {
if (!contextValue) {
throw new Error('useContextSelector requires special context');
}
}

Unexpected and excessive re-renders in components subsribed to context property changes using useContextSelector

I am not sure if I am using this correctly but it doesnt appear to be providing the intended functionality.

I have created sandbox to demonstrate that the subscription mechanism is not isolating renders to subscribed updates
https://codesandbox.io/s/use-context-selector-2-9xsd6

Actual result:

The event emitter updates two counters.
Two components subscribe to counter1 and counter2 updates respectively.
Both are updating when either one is changed.

Expected result:

The subscriber components should only re-render if the value in useContextSelector changes.

useIsoLayoutEffect

Currently, useIsoLayoutEffect is synchronously called in SSR mode, in contrast with how side-effects should never run on SSR mode, infinite re-renders may occur in this case, specially below

useIsoLayoutEffect(() => {
versionRef.current += 1;
setVersion(versionRef.current);
runWithPriority(NormalPriority, () => {
listeners.current.forEach((listener) => {
listener(versionRef.current, value);
});
});
}, [value]);

I think this is an ideal implementation: https://github.com/reduxjs/react-redux/blob/master/src/utils/useIsomorphicLayoutEffect.js

Preact: scheduler

I'm trying to use jotai with Preact with

  "alias": {
    "react": "preact/compat",
    "react-dom": "preact/compat",
    "scheduler": false
  }

but this of course fails with t.unstable_runWithPriority is not a function because scheduler is needed...

Is there a way to make it work?

Type error in useContextSelector

if('v' in action) {}

Doesn't provide type safety to the compiler resulting in action.v remaining as type Value | undefined. This then throws type errors where v is expected to be type Value only

Screen Shot 2022-08-03 at 12 00 40 PM

zero update propagation Context

(Documentation only) feature request

There is a set of cases, when you need to read context only once. Read without any future update, so no subscription is needed - mount effect are a great example of this.

Some libraries already using this pattern, for example sweet-state uses readContext("a hack") to just get the data from React, in a same "no update" mode.

I think this pattern should be documented, but it seems a bit wrong to use useContext to do so, as long as there are some expectations about how useContext is working.

What do you think about useUntrackedContextSelector? The same useContextSelector, but "untracked"?

Warnings in test

Sorry for posting another issue. I just updated to the new React version and the new context-selector version and I'm getting a lot of warnings in my test suit.

Can I do anything to avoid this flood of warnings?

Context.Provider as HOC with memoized children - children still rerender on any state change

here is my setup:

const Screen = withVideoPlayer(() => {
      const load = useContextSelector(VideoPlayerContext, c => c.load);

      console.log("Screen rerendered")
  ...
})
const withVideoPlayer = <P extends object>(WrappedComponent: FC<P>) => {
    const ComponentWithPlayerContext = (props: P) => {
        const controller = useInitVideoPlayerController();

        const Memoized = useMemo(() => memo(WrappedComponent), [WrappedComponent]);

        return (
            <VideoPlayerContext.Provider value={controller}>
                <Memoized {...props} />
            </VideoPlayerContext.Provider>
        );
    };

    return ComponentWithPlayerContext;
};
const useInitVideoPlayerController = () => {

  const load = useCallback(
        async (
            video: IVideo | IVideoTrailer,
            options?: Partial<{
                autoplay: boolean;
                position: number;
            }>,
        ) => {
            dispatch({ type: 'load', payload: { video, options } });
        },
        [],
  );

  ...

  return {
      ... a bunch of state properties and methods wrapped with useCallback
      load,
  };
}

the problem is the Screen component rerenders any time the context is changed, even though it only uses "load" method which is wrapped with useCallback without dependencies. If i remove const load = useVideoPlayer(c=>c.load) from Screen, the rerenders don't happen anymore.

could this be related to this? #86

`yarn compile` fails

Cannot compile this repository's code on macOS 13.0:

image

Same thing as plain text
~/Documents/oss/use-context-selector (main| ✔) node --version
v16.17.0
~/Documents/oss/use-context-selector (main| ✔) yarn compile
yarn run v1.22.19
$ run-s compile:*
$ microbundle build -f modern,umd --globals react=React,react-dom=ReactDOM
Build "use-context-selector" to dist:
        987 B: index.modern.mjs.gz
        884 B: index.modern.mjs.br
       1052 B: index.umd.js.gz
        934 B: index.umd.js.br
$ cp dist/index.modern.js dist/index.modern.mjs && cp dist/index.modern.js.map dist/index.modern.mjs.map
cp: dist/index.modern.js: No such file or directory
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
ERROR: "compile:dom" exited with 1.
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

components using useContextSelector have to be wrapped in memo to prevent surplus re-renders

components using use-context-selector have to be wrapped in memo to prevent surplus re-renders

demo here:

https://codesandbox.io/s/react-use-context-selector-mn8sv?file=/src/App.js

Is this by design, or is it a bug? I cant see any reason why the updates should occur in the non-memoized component.

This is not the case with Redux as components using useSelector do not have to be wrapped by default.

e.g. https://codesandbox.io/s/rtk-counter-53y5q

Thanks

Package scheduler is missing in bundle

Seems that scheduler packages should be not used as a peerDependency, coz this can affect other packages

Module not found: Error: Can't resolve 'scheduler' in '...\projectName\node_modules\formik\node_modules\use-context-selector\dist'

Component updates once when it shouldn't

Hi there!

First let me tell you I'm not sure if this is a bug or if this behavior is intentionally.

To demonstrate my issue, I've created a simple example here.

In that example, I'm console.log in both components just to know when they update. Every time I switch inputs and insert one char, the previous component logs in the console, but only once.

Just wanted ask if I'm doing something wrong or if it's supposed to work like that, because as I understand the component should only update when the selected context also changed, which doesn't seem to be the case there... unless I'm misunderstanding something... :/

Thanks in advance, and nice work with this package :)

Errors got when I use context.provider

Hello, when I try the example code in my project, I got these errors, and page go blank. I have search this problem but cannot find solution.

"react": "^16.8.6",
"use-context-selector": "^1.3.5",
"scheduler": "^0.20.1",

image

Not able to stop the re-rendering of components

Thank you for making such an library, it was a relief for us when we were facing issues of multiple re-renders.

We went through the document and tried the counter example usafe section from https://www.npmjs.com/package/use-context-selector

However, when we added console.log in Counter1 and Counter2 component, both the console logs were getting printed even if we changed value of either of them.
Here is the sandbox for the same - https://codesandbox.io/s/react-use-context-selector-forked-b0z68l?file=/src/index.js

I am sure, we are missing something here. Pl let us know what should be the correct way to use it.
Pl help @dai-shi

`createContext` return type is `any`

So this doesn't seem to be an issue with the library(maybe), but the returned type for createContext is any when I hover over it VSCode, but if I try writing something with it, the autocomplete correctly completes the fields.

Looking at the type definition in the node_modules, and it looks correct to me.

Screenshot 2022-03-04 at 9 17 27 PM

Screenshot 2022-03-04 at 9 17 47 PM

The weirdest thing is if I hover over Context.Provider, it shows the correct type.

What should we do with the warning "Cannot update a component from inside the function body of a different component."

Currently, our Provider invokes subscribed components listeners so that they can force update.
The reason why we need it is that we use the undocumented changedBits = 0 in Context API.

// we call listeners in render intentionally.
// listeners are not technically pure, but
// otherwise we can't get benefits from concurrent mode.
// we make sure to work with double or more invocation of listeners.
listeners.forEach((listener) => {
listener(value);
});

facebook/react#17099 will warn this usage as it does not know about force update.

That's fair. But, unless there's another recommended way, we would need to keep our current approach.

Nobody will use this library if React shows the warning all the time. What should we do?

(Not only this library but also react-tracked and reactive-react-redux.)

mjs module resolution for React Native/Metro is broken

error While trying to resolve module `use-context-selector` from file 
`/Users/groza/Work/welearn/welearn-app/src/components/UI/video-player/VideoPlayerController.tsx`, the package `/Users/groza/Work/welearn/welearn-app/node_modules/use-context-selector/package.json` was successfully found. However, this package itself specifies a `main` module field that could not be resolved (`/Users/groza/Work/welearn/welearn-app/node_modules/use-context-selector/dist/index.native.modern.js`. Indeed, none of these files exist:

  * /Users/groza/Work/welearn/welearn-app/node_modules/use-context-selector/dist/index.native.modern.js(.native|.ios.js|.native.js|.js|.ios.json|.native.json|.json|.ios.ts|.native.ts|.ts|.ios.tsx|.native.tsx|.tsx|.ios.mjs|.native.mjs|.mjs)
  * /Users/groza/Work/welearn/welearn-app/node_modules/use-context-selector/dist/index.native.modern.js/index(.native|.ios.js|.native.js|.js|.ios.json|.native.json|.json|.ios.ts|.native.ts|.ts|.ios.tsx|.native.tsx|.tsx|.ios.mjs|.native.mjs|.mjs).

my metro.config.js (i've already added mjs here):

const defaultSourceExts = require('metro-config/src/defaults/defaults').sourceExts;

module.exports = {
    transformer: {
        getTransformOptions: async () => ({
            transform: {
                experimentalImportSupport: false,
                inlineRequires: true,
            },
        }),
    },
    resolver: {
        sourceExts: process.env.RN_SRC_EXT
            ? [...process.env.RN_SRC_EXT.split(',').concat(defaultSourceExts), 'mjs']
            : [...defaultSourceExts, 'mjs'],
    },
};

manually changing
"react-native": "./dist/index.native.modern.js",
to
"react-native": "./dist/index.native.modern.mjs",
or
"react-native": "./dist/index.native.modern",
allows the build to go through

same thing for manually renaming index.native.modern.mjs to index.native.modern.js

RN version 0.68.0

two questions regarding the useContextUpdate hook

Q1:

If the initial README example is updated to rely on concurrent mode, should the Counter1 component be modified as shown below?

from:

const Counter1 = () => {
  const count1 = useContextSelector(context, v => v[0].count1);
  const setState = useContextSelector(context, v => v[1]);
  const increment = () => setState(s => ({
    ...s,
    count1: s.count1 + 1,
  }));
  return (
    <div>
      <span>Count1: {count1}</span>
      <button type="button" onClick={increment}>+1</button>
      {Math.random()}
    </div>
  );
};

to:

const Counter1 = () => {
  const count1 = useContextSelector(context, v => v[0].count1);
  const setState = useContextSelector(context, v => v[1]);
  const update = useContextUpdate();
  const increment = update(() => setState(s => ({
    ...s,
    count1: s.count1 + 1,
  })));
  return (
    <div>
      <span>Count1: {count1}</span>
      <button type="button" onClick={increment}>+1</button>
      {Math.random()}
    </div>
  );
};

Q2:

I'm trying to improve the performance of an app that uses this library to update multiple contexts. Some contexts only consist of a couple variables, but a couple of the contexts save state as lists with thousands of entries that are updated at 60fps (ideally). Should I only wrap the heavier state updates with the update const or all of the state updates indiscriminately?

`setState` on `useSubscription` apollo update

Is there any chance to update the state when updates from apollo subscription comes in?

In my App.js, whenever the received status is accepted, it should update two values in the state. One is an update on the value of array of objects (state.object[idx].status = accepted) and the other is setting a new value (state.object2 = queried data) from query.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.