Patterns for maybe or union types in React #2259
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 const MyComponent = () => {
const appStore = useStore(AppStore);
if (!appStore.whatever) {
return <></>
}
return <MyComponentInner whatever={appStore.whatever} />
}
const MyComponentInner = (props) => {
const foo = 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. |
Beta Was this translation helpful? Give feedback.
-
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 context
export function assertContext<T extends object | null>(name: string, ctx: T) {
if (!ctx) throw new Error(`Need ${name}Context.Provider`)
return ctx as NonNullable<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
*/
export function useCreateStore<T, Args extends unknown[]>(
Cls: Constructor<T, Args>,
...args: Args
) {
const ref = useRef<T>()
if (ref.current == null) {
ref.current = new Cls(...args)
}
return ref.current
} Store definition: export class FooStore {...}
export const FooStoreContext = createContext<null | FooStore>(null)
export const useFooStore = () => assertContext('FooStore', useContext(FooStoreContext)) Store creation: function App() {
const fooStore = useCreateStore(FooStore, ...)
return <FooStoreContext.Provider value={fooStore}>...</FooStoreContext.Provider>
} Store usage: export const FooComp = observer(function FooComp() {
const fooStore = useFooStore(); // No need for null check, because context is guaranteed to be not-null
console.log(fooStore.whatever)
return (
<div>
...
{/* If you don't want to redraw the whole component */}
<Observer>
{() =>
<Field value={fooStore.whatever}/>
}
</Observer>
...
</div>
)
}) As a general rule for nulls: we avoid using them.
Regarding the
|
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
When it comes to 'doing control flow' (i.e. something is
maybe
or aunion
) there are two possible approaches:mobx-store-provider
to inspect the state of the tree in each component.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:
But then later in the component:
And I can't do that because early return violates the rules of hooks.
I feel like 1. is the 'more correct' approach, but I keep running in to these kinds of problems:
Beta Was this translation helpful? Give feedback.
All reactions