Search code examples
reactjsreduxreact-reduxstoreredux-reducers

How to update redux store tree and then update another tree with data from first?


I have a chart and ui with data inputs for it. I use redux to store data for chart. I have 2 trees. One - for chart component. It contains array of numbers (axis coordinates). And second for ui. It contains array of objects: {axis coordinate, visibility}.

This structure is based on ability to show/hide some data from chart.

enter image description here

Redux store

const initialState = {
  chartSettings: {
    ...
    axisValues: [7, 9, 1, 13, 24, ...]
  },
  chartSettingsData: {
    ...
    axisValues: [
     {value: 7, visibility: true},
     {value: 9, visibility: false},
     ...
    ]
  }
};

I want my chart component to get clear data array from store, without visibility logic. But I need it for ui. So I came to this structure. May be it's wrong. But I have not other ideas.

So, when I click checkbox, I change visibility in store object chartSettingsData. And then, I need to update another tree with data fo chart. I tried clone filtered array after chartSettingsData update in reducer.

case "UPDATE_ITEM_VISIBILITY":
  return {
    ...state,
    chartSettingsData: {
      ...state.chartSettingsData,
      axisValues: state.chartSettingsData.axisValues.map((item, i) =>
        i === index
          ? { value: item.value, visibility: !item.visibility }
          : item
      ),
    },

    chartSettings: {
      ...state.chartSettings,
      axisValues: (() => {
        const filtered = state.chartSettingsData.axisValues.filter(
          (item) => item.visibility
        );
        return filtered.map((item, i) => item.value);
      })(),
    }

But I get data in chartSettings before chartSettingsData been updated. What is the right way to update redux store in this case?


Solution

  • You should construct the two parts of the store in variables (so you can use the new chartSettingsData) and then return:

    case "UPDATE_ITEM_VISIBILITY":
      const chartSettingsData = {
        ...state.chartSettingsData,
        axisValues: state.chartSettingsData.axisValues.map((item, i) =>
          i === index
            ? { value: item.value, visibility: !item.visibility }
            : item
        ),
      };
    
      const chartSettings = {
        ...state.chartSettings,
        axisValues: (() => {
          const filtered = chartSettingsData.axisValues.filter(
            (item) => item.visibility
          );
          return filtered.map((item, i) => item.value);
        })(),
      };
    
      return {
        ...state,
        chartSettingsData,
        chartSettings
      };