avatar

Coderek's blog

Loneliness is the gift of life

A few tricks in React development

Initializing the app using suspense

This trick combines dynamic import of components with initialization code to make a artificial dynamic loading of component. It can make sure the component is initialized before rendering

When to use: use when you have to asynchronously load some resource/data before first render of your app.
Why this is better: So you don't have to handle the initialization logic inside your react component. Especially you don't have to deal with useEffect and manage the state change.

const FailedFallback = <div>failed to load</div>

const createAsyncApp = async () => {
  let Root: JSX.Element
  try {
    // initialization
    networkInit()
    await i18n.init()
    const user = await getUser()

    Root = (
      <ErrorBoundary fallback={FailedFallback}>
        <ConfigProvider>
          <App user={user} />
        </ConfigProvider>
      </ErrorBoundary>
    )
  } catch (e) {
    Root = (
      <div>Failed to load</div>
    )
  }

  return {
    default: () => Root,
    __esModule: true,
  }
}

const AsyncApp = React.lazy(() => createAsyncApp())
ReactDOM.render(
  <Suspense fallback={<PageLoading />}>
    <AsyncApp />
  </Suspense>,
  document.body.querySelector('#root'),
)

Remounting component based on key

When to use: You have a third party component that you can't control it's implementation. But you need it to reinitialize based on some conditions.
Why it is better: Sometimes this is the only way you can conditionally remount a component.

<div key={`${taskName}-${taskStatus}`}>
  <ThirdPartyComponent />
</div>

Expensive intialization of components

This assumes using redux-saga. Redux saga is an awesome way to manage logics of your react app. This especially true when it come to optimize the loading sequence of data.

For example, you have a big data table. Before loading the data, you need to load a bunch of configurations so you can render the filters and paginations properly. And you only need to load those once even after the data table is unmounted.

In this case, you can spawn a take effect that does the initialization. So you can dispatch Init action anywhere in your code, but the effect will only be run once.

export default function* () {
  yield spawn(function* once() {
    yield take(InitTable.type)
    yield initTable()
  })
}

To add on, if there is a heavy effect that shouldn't be triggered too many times, you may use throttle effect to limit the firing frequency. This could be more effective to optimize your app than deboucing the button click.

(End of article)
Hello {{user.name}} ({{user.email}})

Comments ({{comments.length}})

Comments


From {{comment.name}} {{comment.published_at}}
{{comment.body}}
No comment yet