Home > database >  React large array render on svg with drag and select
React large array render on svg with drag and select

Time:12-03

I am using React d3js to render data on svg, i have a large array with data like this

const arrayItemExample = {
  id: 1,
  text: 'Some Text for node',
  x: 100,
  y: 300,
  selected: false,
  dragging: false
}

The list of such elements can reach tens of thousands. The main problem is that when I click on a rendered element or drag it, I update the data on that element:

const handleDragStart = useCallback((id)=>{
  setData(data=>{
    return data.map(item=>{
      if(item.id === id){
        return {
          ...item,
          dragging: true
        }
      }
      return item
    })
  })
},[])

const handleSelect = useCallback((id)=>{
  setData(data=>{
    return data.map(item=>{
      if(item.id === id){
        return {
          ...item,
          selected: true
        }
      }
      return item
    })
  })
},[])

Both of these functions work well on a small amount of data, but if there are 100 or more elements on the page, then clicking or dragging the element slows down the page during the redrawing of elements.

Are there any ways to update the data in a specific element with redrawing its only one? I can't use the component's internal state because I need the total data for the selected and draggable elements: for example, I have selected several elements with ctrl , and when I start dragging one of the selected, the other will also have to be dragged

CodePudding user response:

D3 data sets are most often rendered using SVG, a retained mode graphics model, which is easy to use, but performance is limited. SVG charts can typically handle around 1,000 data points.

Since D3 v4 you’ve also had the option to render charts using canvas, which is an immediate mode graphics model. With Canvas you can expect to render around 10,000 data points whilst maintaining smooth 60fps interactions.

so my recommendation is to use canvas instead of SVG. and if you have time I recommend using WebGL instead.

CodePudding user response:

To update the data for a specific element in an array without redrawing all the elements, you can use the useReducer hook in combination with the useMemo hook. The useReducer hook allows you to define a reducer function that updates the state based on the action that was dispatched. The useMemo hook allows you to compute a memoized value that is only recomputed when one of the dependencies changes.

Here is an example of how you could use the useReducer and useMemo hooks to update the data for a specific element in your array without redrawing all the elements:

const [state, dispatch] = useReducer(reducer, initialState);

const data = useMemo(() => {
  return state.data.map(item => {
    if (item.id === state.selectedId) {
      return {
        ...item,
        selected: true
      };
    } else if (item.id === state.draggingId) {
      return {
        ...item,
        dragging: true
      };
    }
    return item;
  });
}, [state.data, state.selectedId, state.draggingId]);

const handleDragStart = useCallback((id) => {
  dispatch({ type: 'DRAG_START', id });
}, []);

const handleSelect = useCallback((id) => {
  dispatch({ type: 'SELECT', id });
}, []);

In the code above, we define a reducer function using the useReducer hook. The reducer function takes the current state and an action, and returns a new state based on the action. We also define two action creators, handleDragStart and handleSelect, which dispatch the DRAG_START and SELECT actions respectively.

Next, we use the useMemo hook to compute a memoized version of the data array. The useMemo hook takes a function that returns the value to be memoized, and a list of dependencies. In this case, the function returns the updated data array, with the selected and dragging elements updated based on the current selectedId and draggingId in the state.

Finally, we use the data array in our React component to render the elements. Since the data array is memoized, it will only be recomputed when the selectedId or draggingId in the state changes, which ensures

  • Related