question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

API suggestion: deprecate rewind() and use a closure to prevent leaks and race conditions

See original GitHub issue

This is a proposal to deprecate the current API for server-side rendering:

let markup = ReactDOM.renderToString(<App />);
let title = DocumentTitle.rewind();

and replace it with this, inspired by Aphrodite’s SSR API:

let { title, markup } = DocumentTitle.renderStatic(
  () => ReactDOM.renderToString(<App />)
);

This API has two advantages. It is impossible to forget to call rewind. It is also easy to throw an error if DocumentTitle.renderStatic is called in a reentrant way.

You could use this with Aphrodite easily too. The markup field in the result is whatever you return from the closure (can figure out a better name later – I just didn’t want to call it “html” since it might include CSS):

let { title, markup: { html, css } } = DocumentTitle.renderStatic(
  // Aphrodite.renderStatic() returns { html, css }
  () => Aphrodite.renderStatic(() => ReactDOM.renderToString(<App />))
);

This is easy to build in user-space but I think it might be a strictly better API than rewind() so wanted to start a discussion here.

Issue Analytics

  • State:open
  • Created 7 years ago
  • Reactions:2
  • Comments:5

github_iconTop GitHub Comments

3reactions
idecommented, May 29, 2017

Yeah, I think this is mostly independent from supporting concurrent rendering but writing out some hypothetical APIs (especially since React Fiber makes concurrent rendering more relevant) has shifted my opinion a bit.

The closure API would go from:

DocumentTitle.renderStatic(
  () => ReactDOM.renderToString(<App />)
)

and could receive a context value:

// May be time-sliced over multiple rIC/rAF/microtask ticks
DocumentTitle.renderStaticAsync(
  async (sideEffectState) => ReactDOM.renderToStringWithFiberScheduling(
    // Haven't really thought about what goes on in here, probably something with React context
    <App documentTitleSideEffectState={sideEffectState} />
  )
)

In contrast, the rewind() API instead would look look like:

let sideEffectState = DocumentTitle.createSideEffectState();
await ReactDOM.renderToStringWithFiberScheduling(
  <App documentTitleSideEffectState={sideEffectState} />
);
// No more rewind() since all state is in sideEffectState, which gets garbage collected

I kind of like the simplicity of the latter API. I think if react-side-effect were to make a breaking change to its API and require explicitly using sideEffectState and remove rewind(), I’d prefer the latter API. It’s clearer to see when different parts of the code run and you can’t mess it up – you can’t silently forget to call createSideEffectState() the same way you can forget to call rewind().

1reaction
idecommented, Jun 6, 2016

FWIW I wrote a wrapper for react-helmet that does this:

import assert from 'assert';
import Helmet from 'react-helmet';

let isRendering = false;

function renderStatic(render) {
  assert(
    !isRendering,
    `Must not call DocumentHead.renderStatic when already rendering an element`,
  );

  let head;
  let result;
  isRendering = true;
  try {
    result = render();
  } finally {
    head = Helmet.rewind();
    isRendering = false;
  }

  return { head, result };
}

export default { renderStatic };
Read more comments on GitHub >

github_iconTop Results From Across the Web

Developers - API suggestion: deprecate rewind() and use a closure ...
API suggestion : deprecate rewind() and use a closure to prevent leaks and race conditions ... This is a proposal to deprecate the...
Read more >
Avoiding race conditions and memory leaks in React useEffect
The memory leak will happen if the API server took some time to respond and the component was unmounted before the response was...
Read more >
NEWS - third_party/glib - Git at Google
Remove the `-Diconv` configure option, as GLib now uses Meson's built-in logic for ... !2702 tests: Fix a potential race condition in pollable...
Read more >
Changelog - curl
... tests/server/sockfilt.c: avoid race condition without a mutex · tests: fix http2 tests to use CRLF headers · tests: several enumerated type cleanups ......
Read more >
FAQ — Emscripten 3.1.26-git (dev) documentation
You should use the closure compiler, gzip compression on your webserver, etc., ... Compile with -sWASM=0 to disable WebAssembly (and emit equivalent JS ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found