Skip to content
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

How to init state of component when init form? #11

Closed
WangLarry opened this issue Oct 29, 2021 · 6 comments
Closed

How to init state of component when init form? #11

WangLarry opened this issue Oct 29, 2021 · 6 comments
Assignees
Labels
question Further information is requested

Comments

@WangLarry
Copy link

Is your feature request related to a problem? Please describe.
For some components, for example multiselect, it is normal that select's options come from backend server. How to init state(options or items) of these components when init form?
I notice that react-editor custom codes do it when init model data.

Describe the solution you'd like
Can configure component in model, set initComponentState function, then async call it in beforeInitForm.

@WangLarry
Copy link
Author

can init state of component in stateChange function.

     stateChange: (props) => {    
       
        if (!props.prevState) {
          return new Promise((resolve) => {
               // init state ....
            });
          });
        }

        // no more changes needed
        return undefined;
      },

@WangLarry
Copy link
Author

above code can also fix AsyncMultiSelect display 'no options' #47

   AsyncMultiSelect: {
      renderer: AsyncMultiSelect,
      stateChange: (props) => {    
        // if search filter has changed - return object with cleared items and 
        // change isLoading indication to true
        if (!props.prevState || (props.prevState && (props.prevState.searchQuery !== props.state.searchQuery))) {
          return { ...props.state, items: [], isLoading: true };
        }

        // else, if isLoading changes to true,
        // begin search and return promise which resolves an object of: { items: [ ... ], isLoading: false }
        if (props.state.isLoading) {
          return new Promise((resolve) => {
            // mock server call
            mockService.search(props.state.searchQuery || '').then((items) => {
              const viewItems = items.map(x => { return { label: x.name, value: x.id }; });
              resolve({ ...props.state, items: viewItems, isLoading: false }); // items should contain objects that has { label, value }
            });
          });
        }

        // else - no more changes needed
        return undefined;
      },
    },

@galhavivi
Copy link
Owner

galhavivi commented Oct 29, 2021

@WangLarry True :)
There are more ways, lets share them:

  1. You can wait until all your necessary data for the form configuration return form the server (for example enums items form Dropdowns). In this time you will not render the Form object.
    When you have all the data - create the form configuration object, pass it to the react Form component and render it.

Upside - you init all your form configuration just one time in a single point - which is easy to track and change.
Downside - the user might experience a latency in viewing the UI, so if the server taking time to respond this will not be the best UX experience.

  1. You render the Form component with the partial form configuration (i.e with empty items array for the checkboxes).
    When you get the respond from the server - create a new model object and pass it to the Form component - this will trigger a new init for the form.

Upside - better UX experience (the user immediately see the ui of the form when the page is loaded).
Downside - 2 inits, and the user might be quick enough to do some action on the form which might be overwritten. Also might affect tests as well.

  1. As you mentioned - you can use "stateChange" component to init the component state items - which is also run during the init process.
    Here is a demo example: https://galhavivi.github.io/cofi/demo-react-form.html#/basics/async-state/html

Upside - better UX experience (the user immediately see the ui of the form when the page is loaded). Also all the component "logic" and configuration remains in the component scope.
Downside - if you want a single point in the system which will have all the initial form configuration - this will not serve it.
Also - if you have multiple fields components which require initial data from the server - this might cause multiple calls to the server, instead of just one (But actually if your'e being smart you can have a server which fetch you all the components data in one call and cache it. And all the component use it to get the data, and only the first component which called it will cause the actual call to the server to occur. the rest will wait for the response.)

Note:
Hooks of Side effects like "beforeInitForm" (before and after actions) are not meant to trigger any change in the form structure. For that we have the "actions" objects. Side effects are for stuff like - logging to the DB, google analytics or other stuff. This is why we don't pass the "actions" object to these hooks.

Choose the best practice for your app :)

@galhavivi galhavivi self-assigned this Oct 29, 2021
@galhavivi galhavivi added the question Further information is requested label Oct 29, 2021
@WangLarry
Copy link
Author

Also all the component "logic" and configuration remains in the component scope.
It's important because we can config form, not write 'custom' codes for every form.

@galhavivi
Copy link
Owner

@WangLarry
True and you can use the same form configuration for multiple forms :)
For example if you have the field of "lastUpdated" for multiple forms you can define it only once - in a shared location.

@WangLarry
Copy link
Author

I think that performance is considered lately.

  1. This library focus enterprise program
  2. Can use cache to improve performance.
  3. Can use server render ...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants