Uniforms: Server Side Rendering - Consistent Id

Created on 30 Aug 2018  Â·  14Comments  Â·  Source: vazco/uniforms

modules.js?hash=e30b5ce507c9b9d1b92f0b95d086866014bfef1a:2830 Warning: Prop `id` did not match. Server: "uniforms-0001-0001" Client: "uniforms-0000-0001"

Constantly refreshing it takes me to:

Warning: Prop `id` did not match. Server: "uniforms-0005-0001" Client: "uniforms-0000-0001"

Is there a way to sort-of reset the uniform id ?

bug

All 14 comments

After some investigations I've seen this and it was marked as solved:
https://github.com/vazco/uniforms/blob/master/packages/uniforms/src/randomIds.js

But how is it really solved ? I think it would be good if we can provide a counter or maybe allow to specify an id={} at form top level ?

Hi @theodorDiaconu. As you can see here, BaseForm creates a fresh generator, based on own id. In this case, setting the form id should be enough.

@radekmie indeed it does, but we need a way to reset that counter somehow. Or simply bypass it, because if I constantly refresh the page that counter increases or promote a way to garbage collect it.

What is the reason for this id generation btw ?

Which generator and why? You mean the default argument value of randomIds? It's not called (therefore incremented) if you pass it an argument. Also, what garbage collection you mean? There's nothing accumulated.

The reason is to provide each field an id. In this case, due to the same reasons as here (SSR), #40 was reported. Since then, these generators are deterministic.

I was referring to why do you need to set an id for the form. What is the purpose for it ? Can we not have a form id at all ?

I still don't understand why uniforms-0001 gets incremented, looking at the code, it seems that counter = 0 each time.

If I do provide an id="xxx" to the form the error disappears which is great and I think it's fine for now and we can close this. But I'm still a bit confused.

When the form is created, it creates a new generator here. Then, it's passed down to the fields, so they can use it. The counter starts at 0, but it's incremented two lines below.

If you provide the form an id, then you change the prefix, which is also generated.

As it's clear and working now, I'm closing.

Nice. The weird thing that remains is why the heck wouldn't the form be "destroyed" after Server-Side Rendering has done it's thing. Keeping it in memory seems trouble-some.

It is destroyed, as it's out of the scope. The only thing it changed, is the ++ of the default prefix generator.

this also happens for me. on every server side render, the id gets incremented. I try to find out whats going wrong here.

Edit:

ok, its pretty clear why this happens:

the random id has the structure <formid>-<fieldId>.

  • if you pass a formId (which i personally try to avoid like the pest, because they need to be unique accross the page), then this one will get used for the first part
  • if you dont pass one (which is in my opinion recommended), uniforms generates one by incrementing a number on every invokation. It does so by having a "global" counter. On the client, this works fine, because it guarantees that every form will get a different id.
  • This does not work on the server however, because this counter will never reset.

Possible solutions:

  • always pass an id to forms (personally i strongly disagree with this one)
  • add an api to reset this randomId generator (also not very clean, because you have to do this on every SSR, but probably simplest to do)
  • Or best: Force the user to Wrap his App in a React.createContext provider that provides this id-incrementor.

React.createContext is able to provide a "global" per react-tree, which would be the right api for this problem here.

Some more tipps about SSR and random values:

If you have components in your app that relies on randoms, you will usually run into a similar problem. My usual solution for this is to have a React.createContext-pair that provides a random-seed. Every random-generator will use this seed to create any random value (using seed-random). The server will define a seed for every request (e.g. itself a non-seeded randomId, or the current timestamp or whatever) and pass it as a global variable to the client (e.g. writing a script-tag with window.__randomseed = ....). both server and client will have a context-provider that provide this value. The server will use its own generated value, while the client uses the one from window.__randomseed.

@radekmie can you reopen?

@macrozone: I won't reopen as it's a solved topic.

If the default ID generation works for you - no problem. If not, then you can use id on your forms. Yes, they need to be unique and it's something to think about, but it's not _hard_. In the end, sha512(__file) is also a solution. If id is not applicable, using an outside (context, API, whatever) seed/generator is not viable, as it has the same problems as the current one, but there's one API more to support.

As a total workaround, which can use context API or Math.random if you want, just create your own Form, which will override default randomId with your own implementation. It has to be a function, which will return _next_ (kind of) ID.

There is a comment about workaround for ssr in the randomId file, but the
randomId implementation is broken for SSR, that‘s why i think its
worthwhile opening the issue.

Its ok for uniforms to not support SSR or ask the user to provide an id for
every form or a custom randomId function, but maybe we should have this
caveat documented, because reading this issue, its not obvious to everyone
Radosław Miernik notifications@github.com schrieb am Mo. 26. Nov. 2018 um
20:51:

@macrozone https://github.com/macrozone: I won't reopen as it's a
solved topic.

If the default ID generation works for you - no problem. If not, then you
can use id on your forms. Yes, they need to be unique and it's something
to think about, but it's not hard. In the end, sha512(__file) is also a
solution. If id is not applicable, using an outside (context, API,
whatever) seed/generator is not viable, as it has the same problems as the
current one, but there's one API more to support.

As a total workaround, which can use context API or Math.random if you
want, just create your own Form, which will override default randomId
https://github.com/vazco/uniforms/blob/master/packages/uniforms/src/BaseForm.js#L103
with your own implementation. It has to be a function, which will return
next (kind of) ID.

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/vazco/uniforms/issues/459#issuecomment-441774669, or mute
the thread
https://github.com/notifications/unsubscribe-auth/AB4YgWKfY57IyWNJBDhGrRSIDSu9_ZDhks5uzEZYgaJpZM4WS6oD
.

>

ran into this again in a new project. This also happens if you do snapshot testing of course.

I think it is worth rethinking. It would be best if uniforms would not rely on ids at all. This would solve many problems. :-/

It's in particular a nasty problem, because you might not run into it in the beginning of development, but later on. Also as a developer i don't understand why i need to give ids to these components, I don't need them. It seems to be an internal detail and should be handled internally.

Again, this can be solved by explicitly providing all IDs.

It seems to be an internal detail and should be handled internally.

In a way, yes. The problem is we did it a long time ago to make the <label> tags work properly across themes. We cannot remove it right now, due to the compatibility, but we may think about it in the next major release.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

serkandurusoy picture serkandurusoy  Â·  5Comments

arrygoo picture arrygoo  Â·  3Comments

dacioromero picture dacioromero  Â·  5Comments

danilomiranda picture danilomiranda  Â·  4Comments

vfonic picture vfonic  Â·  3Comments