skip to Main Content

I am new to React and have a mostly OOP experience. I am trying to create a Map component that allows easily changing its config (zoom level, layers…).

Here is the solution I came up with: https://stackblitz.com/edit/stackblitz-starters-fmmajh?devToolsHeight=33&file=src%2FApp.tsx . Sadly MapComponent does not rerender when zoomLevel changes.


I am fully aware that this is probably the wrong way to do it and I am abusing functional prog principles.

But all "conventional" solutions would require coworkers using my Map component to set up states and functions around it to be able to update the zoom.

I would like to be as easy as calling a function, like I tried doing it (Map.setZoom(1)), even if the syntax is a bit different

Is that possible in React? Thanks for the help

2

Answers


  1. There is exactly one way to cause a rerender in react: set state1. So to do what you want, you will need to make a state. This typically looks something like the following

    function MapUsage() {
      const [zoom, setZoom] = useState(0.5);
      return (
        <>
          <Map zoomLevel={zoom} />
          <button onClick={() => setZoom(1)}>Zoom</button>
        </>
      )
    }
    

    But all "conventional" solutions would require coworkers using my Map component to set up states and functions around it to be able to update the zoom.

    There are a few options for how to share this code, without them having to implement their own state. Option 1 is to write a component which implements the state, and they use that. Indeed, <MapUsage> might be exactly that component. Ie, your coworkers could just use <MapUsage>, and never use <Map> directly.

    Option 2: if this logic needs to be used in a wide variety of components, and it’s complicated enough that you don’t want each component to do its own logic, then you could put the logic into a hook:

    const useMap = () => {
      const [zoom, setZoom] = useState(0.5);
      const zoomMapBy = (offset: number) {
        setZoom(prev => prev + offset);    
      }
    
      const zoomMapTo = (newZoom: number) {
        setZoom(newZoom);
      }
    
      return { 
        element: <Map zoomLevel={zoom} />
        zoom, 
        zoomMapBy,
        zoomMapTo
      }
    } 
    
    // used like:
    
    function MapUsage() {
      const { element, zoomMapTo } = useMap();
      return (
        <>
          {element}
          <button onClick={() => zoomMapTo(1)}>Zoom</button>
        </>
      )
    }
    

    1) ok, technically there’s also forceUpdate in class components, but don’t use that

    Login or Signup to reply.
  2. Yes, it’s possible to achieve the behavior you want in React, where you can easily change the configuration of a Map component, including the zoom level, without having to set up additional states and functions around it. However, there are some adjustments you can make to your code to achieve this.

    In your provided StackBlitz example, the issue is that the zoomLevel variable is a local variable inside the App component, and changes to it do not trigger a re-render of the MapComponent. To make it work the way you want, you should lift the state up to the parent component (in this case, the App component) and pass it as a prop to the MapComponent. Here’s an example of how you can do it:

    import React, { useState } from "react";
    import ReactDOM from "react-dom";
    
    function MapComponent({ zoomLevel }) {
      return <div>Map with Zoom Level: {zoomLevel}</div>;
    }
    
    function App() {
      const [zoomLevel, setZoomLevel] = useState(5);
    
      // Function to update the zoom level
      const setZoom = (newZoomLevel) => {
        setZoomLevel(newZoomLevel);
      };
    
      return (
        <div>
          <h1>Map App</h1>
          <button onClick={() => setZoom(10)}>Set Zoom to 10</button>
          <MapComponent zoomLevel={zoomLevel} />
        </div>
      );
    }
    
    ReactDOM.render(<App />, document.getElementById("root"));
    

    In this example, the zoomLevel state is managed in the App component, and it’s passed down as a prop to the MapComponent. When you click the "Set Zoom to 10" button, it will update the zoomLevel state, causing a re-render of the MapComponent with the updated zoom level.

    This approach follows the React way of managing state and props, making it easy to control the configuration of your Map component while maintaining a clean and predictable structure.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search