How to combine updation of multiple Refinement List into React Native

Into my React Native app, I am using useRefinementList of react-instantsearch-hooks for my refinements
Currently I have around 8 filters included, more to be added
On selecting any filter item from refinement list A, all other refinement list gets updated

This is how I am doing currently

const { items, refine } = useRefinementList({
    attribute: 'A',
    limit: 9999,
  })

Same thing goes on for rest 7 filters, all into one single component
So on refining single filter item, there happens to be latency in updating the effect of selected item

My 1st question, is the above mentioned way a proper approach?
2nd question, calling useRefinementList for 8 times in single component? Thats weird way of doing it. Is there an efficient approach? Which should also reduce the latency described above

@haroen Can you suggest something here

You can use useInstantSearch().setIndexUiState() to set the state of multiple widgets at the same time freely

@haroen I am not clear. Can you share an example for this

You can call setIndexUiState(state => ({ ...state, refinementList: { ...state.refinementList, attribte1: value1, attribute2: value2 ...}})), then you’ll need to loop over all refinements to get the refined values for each attribute

@haroen This would not help me in fixing latency

Yes, it would as you don’t call refine on all of your widgets, but only a single network request happens when you call setUiState

@haroen I am new to algolia and the docs do not explain me clearly about setIndexUiState and refine
How are both these used

@haroen Are setIndexUiState and refine used together? or How?

You use it instead of refine

@haroen I did experiment with setIndexUiState
But there happens to be additional latency in case of setIndexUiState
refine works still better
All this in case of 4 filters

Whereas I have 8 filters to include, refine happens to slow down in this case
setIndexUiState is not good fit here, as it was slow with 4 filters itself

I have spent lot of time to get this working, please suggest me workaround

@haroen Can you suggest me something here
My app has 2 new filters added to list, so a total of 10 filters
Its getting difficult to keep good performance

I think it’s best that you either contact support or create a reproduction and open an issue. Without using the exact code you’re using and how you’re measuring it, we won’t be able to help.

I don’t see how calling setUiState once would be slower than calling refine many times.

To combine the update of multiple Refinement Lists in React Native, you can create a central state management approach using a tracking combine state container like Redux or MobX. This allows you to manage the state of your Refinement Lists centrally, making it easier to update them collectively and keep your UI synchronized. This approach improves code maintainability and reduces redundancy. If you need further guidance or specific code examples, please let me know.

@causeymackenzieson62 Thank you for helping in
Code Example would be more helpful

@causeymackenzieson62 Can you share example?

@haroen I tried with setIndexUiState to avoid refine multiple times
But useRefinementList is invoked on every setIndexUiState

const { items: items1 } = useRefinementList({
    attribute: 'attribute1',
    limit: 9999,
  })
  const { items: items2 } = useRefinementList({
    attribute: 'attribute2',
    limit: 9999,
  })
  ...
  const { items: items10 } = useRefinementList({
    attribute: 'attribute10',
    limit: 9999,
  })

  const handleRefine = (item) => {
    setIndexUiState((prevIndexUiState) => ({
      ...prevIndexUiState,
      refinementList: {
        ...prevIndexUiState?.refinementList,
        attribute1: [
          ...prevIndexUiState?.refinementList?.attribute1,
          item?.value,
        ],
        attribute2: [
          ...prevIndexUiState?.refinementList?.attribute2,
          item?.value,
        ],
      },
    }))
  }

  return (
    <Modal>
      <Pressable onPress={() => handleRefine(item)}>
        <Text>{item?.label}</Text>
      </Pressable>
    </Modal>
  )

What am I doing wrong here?

@haroen Can you please check this once, I have mentioned code snippet

I don’t see anything wrong, although having all the useRefinementLists in the same component that updates when you refine would possibly cause the widgets to remount (if you have any props that aren’t stable for example).

Moving the order to something like this would help:

<App>
  <RefinementLists />
  <Ui />
</App>

With RefinementLists having merely the useRefinementList calls (returning null)

And Ui still having the modal, refine using setUiState. The items can be read from renderState readable from a custom widget:

const connectAllRefinementLists =
  (renderFn, unmountFn = () => {}) =>
  (widgetParams) => ({
    $$type: 'my.combinedRefinementLists',
    init(initOptions) {
      renderFn(
        {
          ...this.getWidgetRenderState(initOptions),
          instantSearchInstance: initOptions.instantSearchInstance,
        },
        true
      );
    },
    render(renderOptions) {
      renderFn(
        {
          ...this.getWidgetRenderState(renderOptions),
          instantSearchInstance: renderOptions.instantSearchInstance,
        },
        false
      );
    },
    getWidgetRenderState({ instantSearchInstance, parent }) {
      return {
        renderState:
          instantSearchInstance.renderState[parent.getIndexId()].refinementList,
        setIndexUiState: (nextIndexUiState) => {
          parent.setIndexUiState(nextIndexUiState);
        },
      };
    },
  });

function useAllRefinementLists(props, additionalWidgetProperties) {
  return useConnector(
    connectAllRefinementLists,
    props,
    additionalWidgetProperties
  );
}

function Ui() {
  const {renderState, setIndexUiState} = useAllRefinementLists()

  return ...
}

Yes I am doing exactly the same way
RefinementLists is doing all the useRefinement calls and passing to Modal (<Ui>) component which handles refine through setUiState

<App>
  <RefinementLists items1={items1} ... items10={items10}  />
  <Ui items1 ... items10 />
</App>