Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: add migration example in v3 create context #1524

Merged
merged 3 commits into from
Jan 10, 2023

Conversation

dai-shi
Copy link
Member

@dai-shi dai-shi commented Jan 10, 2023

@codesandbox-ci
Copy link

codesandbox-ci bot commented Jan 10, 2023

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

Latest deployment of this branch, based on commit b09b385:

Sandbox Source
React Configuration
React Typescript Configuration
React Browserify Configuration
React Snowpack Configuration
React Parcel Configuration
Next.js Configuration
@pavlobu/zustand demo Configuration

@github-actions
Copy link

github-actions bot commented Jan 10, 2023

Size Change: 0 B

Total Size: 40.1 kB

ℹ️ View Unchanged
Filename Size
dist/context.js 775 B
dist/esm/context.js 581 B
dist/esm/index.js 598 B
dist/esm/middleware.js 3.79 kB
dist/esm/middleware/immer.js 210 B
dist/esm/shallow.js 469 B
dist/esm/vanilla.js 612 B
dist/index.js 751 B
dist/middleware.js 4.34 kB
dist/middleware/immer.js 328 B
dist/shallow.js 1.06 kB
dist/system/context.development.js 688 B
dist/system/context.production.js 365 B
dist/system/index.development.js 763 B
dist/system/index.production.js 468 B
dist/system/middleware.development.js 3.91 kB
dist/system/middleware.production.js 2.69 kB
dist/system/middleware/immer.development.js 292 B
dist/system/middleware/immer.production.js 187 B
dist/system/shallow.development.js 545 B
dist/system/shallow.production.js 415 B
dist/system/vanilla.development.js 658 B
dist/system/vanilla.production.js 372 B
dist/umd/context.development.js 876 B
dist/umd/context.production.js 533 B
dist/umd/index.development.js 878 B
dist/umd/index.production.js 595 B
dist/umd/middleware.development.js 4.48 kB
dist/umd/middleware.production.js 2.97 kB
dist/umd/middleware/immer.development.js 472 B
dist/umd/middleware/immer.production.js 337 B
dist/umd/shallow.development.js 1.22 kB
dist/umd/shallow.production.js 947 B
dist/umd/vanilla.development.js 785 B
dist/umd/vanilla.production.js 467 B
dist/vanilla.js 650 B

compressed-size-action

@dai-shi
Copy link
Member Author

dai-shi commented Jan 10, 2023

@chrisk-7777 @sewera @dbritto-dev @charkour
This is like a minimal migration guide. Wish to have your help.

Copy link
Collaborator

@sewera sewera left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clear and straightforward. Approved :)

Copy link
Collaborator

@chrisk-7777 chrisk-7777 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@dai-shi dai-shi merged commit 55d0c3a into main Jan 10, 2023
@dai-shi dai-shi deleted the docs/v3-context-migration branch January 10, 2023 12:54
@TkDodo
Copy link
Collaborator

TkDodo commented Jan 10, 2023

@dai-shi what would be your recommendation to initialize a zustand store from props? We've used createContext for this up until now. Could we just wrap createStore with useMemo inside the App component?

const StoreContext = createContext()

const App = ({ initialState }) => {
  const store = useMemo(() => createStore(initialState), [initialState])

  return (
    <StoreContext.Provider value={store}>
      ...
    </StoreContext.Provider>
  )
}

?

@dai-shi
Copy link
Member Author

dai-shi commented Jan 10, 2023

Yeah, that's the way to go. Probably, useRef would be better.

@charkour
Copy link
Collaborator

@TkDodo, here's the zustand guide for initializing a zustand store with props using useRef as Daishi mentioned. In preparation for the removal of createContext in zustand v5, my team released our own package for it. Hopefully, that is helpful for your team.

@dai-shi, should the React/context migration example include a link to the guide "Initialize State With Props"? It has a nice walkthrough of how to use React Context to init stores. When I was trying to migrate our codebase, my team and I had trouble because the zustand + context documentation was separated in many different spots. What do you think?

@TkDodo
Copy link
Collaborator

TkDodo commented Jan 10, 2023

Thanks for the link. Just a small preference: I would choose useState over useRef in the docs:

-  const storeRef = useRef<BearStore>()
-  if (!storeRef.current) {
-    storeRef.current = createBearStore(props)
-  }
+  const [store] = useState() => createBearStore(props))

This has only upsides :)

@charkour
Copy link
Collaborator

Would this also be equivalent in behavior? This is stretching my understanding of React's state behavior.

-  const storeRef = useRef<BearStore>()
-  if (!storeRef.current) {
-    storeRef.current = createBearStore(props)
-  }
+  const store = useRef(createBearStore(props)).current

@TkDodo
Copy link
Collaborator

TkDodo commented Jan 10, 2023

no it's not strictly equivalent, because useRef has no "lazy initializer". So in this case, createBearStore(props) is executed every time, then it is passed to useRef, where only the result of the first render is taken into account. It's minor, but it's still different.

with useState, you can have the initializer function, which is only evaluated once.

@charkour
Copy link
Collaborator

Right, I always forget about lazy init. Thank you!

@dai-shi
Copy link
Member Author

dai-shi commented Jan 10, 2023

@TkDodo #1524 (comment)

This has only upsides :)

I don't prefer using useState for lazy init.
It should be less efficient technically. Not a right tool, as it's not "state".
My recommendation is use-constant.

@axelboc
Copy link

axelboc commented Jan 18, 2023

Is there an easy way to type the line below? I'd like useMyStore to have the same type as useStore (with the same generics and overrides). I've tried a few things, including const useMyStore: typeof useStore = ... but it doesn't seem to work.

export const useMyStore = (selector) => useStore(useContext(MyContext), selector);

@dai-shi
Copy link
Member Author

dai-shi commented Jan 19, 2023

You don't need to replicate the type, instead:

const useMyStore = <T>(selector: (state: MyState) => T) => useStore(useContext(MyContext), selector);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants