JvectorMap rerendering proper markers after setState reactjs

Viewed 1292

The problem I'm having is whenever the data that is passed into the jvectormap changes, the map doesn't reflect the changes.

Inside my state, I have two sets of data: data1 and data2. Inside my render method, I have a button where once clicked, it'll change this.state.data1 to have the same contents as this.state.data2 since the map takes this.state.data1 as the value for markers. Here is my render function:

  render() {
    return (
      <div>
        <a
          href="#"
          onClick={() =>
            this.setState({ data1: this.state.data2 }, () =>
              console.log(this.state.data1)
            )
          }
        >
          Click
        </a>
        <div style={{ width: 500, height: 300 }}>
          <VectorMap
            map={"world_mill"}
            backgroundColor="#FFFFF"
            markerStyle={{
              initial: {
                fill: "#FFFF",
                stroke: "#383f47"
              }
            }}
            series={{
              markers: [
                {
                  attribute: "r",
                  scale: [5, 20],
                  values: [60, 6, 54],
                  normalizeFunction: "polynomial"
                }
              ]
            }}
            regionStyle={{
              initial: {
                fill: "#128da7"
              },
              hover: {
                fill: "#A0D1DC"
              }
            }}
            markers={this.state.data1}
            ref="map"
            containerStyle={{
              width: "100%",
              height: "100%"
            }}
            containerClassName="map"
          />
        </div>
      </div>
    );
  }
}

The whole code is simple and can be found here: https://codesandbox.io/s/2vx2k1vl9n. As you can see, in the onClick method for the button, I print data1 after setting the state in order to make sure that its value changes which it does, but it's not being reflected on the map. Can anyone help me with this?

Thanks in advance!

2 Answers

The problem is basically not in your code. I just went to react-jvectormap repo and had a look at the code because I suspect that there is something denying re-rendering.

Turns out the map isn't being rendered by ReactJS, instead it is being rendered by jQuery.

I went and forked the project and altered its code so that it would work with the example given above.

I'll do a pull request to their repo, meanwhile, you can try and use my version here: https://github.com/seifsg/react-jvectormap

And this is the file that I made the change to, you might just want to copy and paste it to its right place within your node_modules folder: https://github.com/seifsg/react-jvectormap/blob/master/src/lib/components/VectorMap.js

So to have it working with your code:

  • Copy the modified file to the corresponding node_modules directory

  • In the same directory, execute npm i then npm run build that should generate a new build file and should make your changes work.

Here is an example using the build file only: codesandbox.io/s/kw90mx7647

If you don't want to work on forked stuff, here is a work around.

First create a boolean state to how/hide the map:

const [isShowMap, setIsShowMap] = useState(true);

Attached this state to show/hide the map html:

{ isShowMap && <VectorMap... }

On any change in props or any data, just turn this flag off and on again with setTimeout:

useEffect(()=>{
  setIsShowMap(false);
  setTimeout(()=>{
    setIsShowMap(true);
  })
}, [prop1, prop2]);

As it is just a work around, you will experience a tittle flicker.

Related