- Notifications
You must be signed in to change notification settings - Fork638
Patterns for maybe or union types in React#2259
-
When it comes to 'doing control flow' (i.e. something is
Here's the problem: With 1. Things get weird because, as I understand it, passing model instances leads to the kind of errors I'm running in to. With 2. I want to do this: constappStore=useStore(AppStore);if(!appStore.whatever){return<></>}// more logic But then later in the component: constfoo=useHook(appStore.whatever) And I can't do that because early return violates therules of hooks. I feel like 1. is the 'more correct' approach, but I keep running in to these kinds of problems: |
BetaWas this translation helpful?Give feedback.
All reactions
Replies: 2 comments 2 replies
-
Don't you just love React? 😭 You could consider something like suspense, or depending on what kind of control you have over constMyComponent=()=>{constappStore=useStore(AppStore);if(!appStore.whatever){return<></>}return<MyComponentInnerwhatever={appStore.whatever}/>}constMyComponentInner=(props)=>{constfoo=useHook(props.whatever)// more logic} Breaking up your components in this way is my go-to when I need to get around the rules of hooks. |
BetaWas this translation helpful?Give feedback.
All reactions
-
I'm confused r.e. the that inner component pattern: |
BetaWas this translation helpful?Give feedback.
All reactions
-
Should be no reason to not do that. We do it all the time at my company 🙂 But if I'm reading things correctly, I think I missed the specifics of what you're working through. My bad! Sounds like you have a model instance that is alive when you render the component, but not alive sometime later. We definitely have had to deal with that issue too, but overall I don't think it's been a major source of pain for us. We have a few Maybe instead of talking in the abstract, you could provide a minimal example that shows the issue you're running into and we could work through that together? The first thing that's popping into my head would be some kind of wrapper (like how there's |
BetaWas this translation helpful?Give feedback.
All reactions
😄 1
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
-
Sorry if I answer out of place (maybe I didn't grab the core problem here). Here's how we do it all the time with Mobx. First, a couple of utility functions: // A function to get rid of null contextexportfunctionassertContext<Textendsobject|null>(name:string,ctx:T){if(!ctx)thrownewError(`Need${name}Context.Provider`)returnctxasNonNullable<T>}// An optional utility to create store only one time/** * Creates a class by its name and constructor parameters. * Useful for replacing lines like: `const store = useRef(new Cls(arg1, arg2...)).current`, * as it is not creating classes every render. *@param Cls classname *@param args constructor arguments */exportfunctionuseCreateStore<T,Argsextendsunknown[]>(Cls:Constructor<T,Args>, ...args:Args){constref=useRef<T>()if(ref.current==null){ref.current=newCls(...args)}returnref.current} Store definition: exportclassFooStore{...}exportconstFooStoreContext=createContext<null|FooStore>(null)exportconstuseFooStore=()=>assertContext('FooStore',useContext(FooStoreContext)) Store creation: functionApp(){constfooStore=useCreateStore(FooStore, ...)return<FooStoreContext.Providervalue={fooStore}>...</FooStoreContext.Provider>} Store usage: exportconstFooComp=observer(functionFooComp(){constfooStore=useFooStore();// No need for null check, because context is guaranteed to be not-nullconsole.log(fooStore.whatever)return(<div> ...{/* If you don't want to redraw the whole component */}<Observer>{()=><Fieldvalue={fooStore.whatever}/>}</Observer> ...</div>)}) As a general rule for nulls: we avoid using them.
Regarding the |
BetaWas this translation helpful?Give feedback.