Skip to content

Candidate alternative strategy for front-end state management 2 #746

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Aug 11, 2021

Conversation

mturoci
Copy link
Collaborator

@mturoci mturoci commented Apr 16, 2021

This PR assumes model.name to be unique and requires zero server overhead. It also assumes name to be present and to be an identifier.

React destroys and creates a new component only if model.name changes.

@lo5 wdyt

Closes #150

@mturoci mturoci requested a review from lo5 as a code owner April 16, 2021 08:24
@mturoci mturoci requested a review from geomodular April 16, 2021 08:24
@lo5
Copy link
Member

lo5 commented Apr 17, 2021

The reason we have xid() in the first place is that not all components have a name, and having to name all components in an app is cumbersome.

What we need is a way to generate a React-friendly key instead of xid(), regardless of the name (although using a name if present is not a bad idea).

@mturoci
Copy link
Collaborator Author

mturoci commented May 19, 2021

I see, the only other alternative that comes to my mind is:

<XComponent key={`${Object.keys(m)[0]}-${i}`} model={m} />

componentType-order which basically says - as long as the order and component type is the same as previous render, just update props, otherwise destroy current component and create a new one.

This would:

q.page['example'].items[0].text.content = f'Selected date: {q.args.date_trigger}'
q.page['example'].items[1].date_picker.label = 'New label'
q.page['example'].items[1].date_picker.trigger = False

However, this would be problematic:

#  Let's say the card is initialized with these items.
q.page['example'] = ui.form_card(box='1 1 4 10', items=[
    ui.text(f'date_trigger={q.args.date_trigger}'),
    ui.date_picker(name='date_trigger', label='Pick a date', trigger=True),
])
...
# After an action, we decide to change the items, but types and order remains the same.
q.page['example'].items = [
    ui.text('New text'),
    ui.date_picker(name='new_date_trigger', label='New name', trigger=True),
]

In this case, IMO, the correct behavior would be to recreate the components instead of updating the existing ones since we got new python references. Not sure though, if achievable with the proposed approach.

cc @lo5 @geomodular

@mturoci
Copy link
Collaborator Author

mturoci commented Aug 10, 2021

As proposed, the key used for determining whether a form item should be recreated or updated is constructed in the following manner:

  • if name is present use that - as long as the name within form is the same, the component is updated
  • if name is not present, check position within form items, if type of item and position is the same, update

I consider ^^ heuristic approach the best. Another possible alternative would be to replace the heuristic order with xid() which would recreate all the components without name on every data update. This could be theoretically fine too since update / recreate question basically matters only if a component needs to keep its own state (textbox, checkbox etc.) and these components must have name specified in order to work. The rest of form items is presentational (text, plots, etc) which don't need to hold any state and simply display passed data.

In order to make updates work, I had to refactor all the existing form components from bond to native React functional components due to bond providing stale props on update.

@lo5 please let me know if that strategy sounds good to you before merging.

@lo5
Copy link
Member

lo5 commented Aug 10, 2021

@mturoci - sounds great! Thanks for the changes.

@mturoci mturoci merged commit 0dbb7e2 into master Aug 11, 2021
@mturoci mturoci deleted the fix/issue-150 branch August 11, 2021 09:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Textbox with trigger=true clears itself after submitting value
2 participants