mobxjs / mobx-utils

Utility functions and common patterns for MobX
MIT License
1.19k stars 126 forks source link

computedFn warnings when React SSR rendering via useStaticRendering #278

Open jashmoreindeed opened 4 years ago

jashmoreindeed commented 4 years ago

Hey,

We have an application using mobx that is performing Server Side Rendering with Client Side hydration and we are getting a bunch of warnings on our server: invoking a computedFn from outside an reactive context won't be memoized, unless keepAlive is set.

We are basically doing something like:

// Main-server.tsx
useStaticRendering(true);

export const render = (props: Props): string => {
    return renderToStaticMarkup(<Main {...props} />);
};

Where our component calls into the store method with is a computed value

// component.tsx in the render method
const person = myStore.getPersonWithAge(props.name);
// store.ts
export class MyStore {
  @observable
  public people: Person[] = [];

  public getPersonWithAge: (name: string) => Person | undefined = computedFn(
    function findPerson(this: MyStore, name: string): Person | undefined {
      return this.people.find((p) => p.name === name);
    }
  );

You can see a minimal reproducible example here: https://codesandbox.io/s/elated-bardeen-qw3vo where you can toggle the useStaticRendering to true or false to represent the client or server rendering. The warning shows up when this value is set to true.

Looking at the mobx code this makes sense to me why the warning is occurring as we are using the computed value when not in the reactive environment as it is server side rendering and won't run effects.

I have tried to ignore it with mobx as suggested in but that doesn't seem to have worked as that property doesn't exist in the configuration options:

mobx.configure({
    // @ts-ignore doesn't exist in typescript
    warnOnUnsafeComputationReads: false,

    // looks similar but doesn't work
    computedRequiresReaction: false
})

I am wondering whether we are doing something wrong and shouldn't actually get these warnings or whether this is a problem with the computedFn method not realising that it is SSR and may not need to warn us? Let me know if this issue should exist in the mobx-react repo.

mweststrate commented 4 years ago

probably computedFn should have an option to fix this. as a quick around you could introduce your own utility:

import {computedFn as originalComputedFn } from "mobx-utils"
import {isStaticRenderingEnabled /*from top of my head*/ } from "mobx-react" /* or lite, pending your setup */

export function computedFn<T>(fn: T): T { 
  return isStaticRenderingEnabled() ? fn : originalComputedFn(fn)
}
jashmoreindeed commented 4 years ago

Great, a nice and easy workaround.