Home  >  Q&A  >  body text

The useState hook changes the state of all components, not just the expected one.

I'm using React. I'm trying to change the style of the image that is clicked. But the state is applied to all elements using this function. onClick event is applied to the picture. Click on one and the border color of the other images should change to #a2a0ff. Only clicked images should have the color #4D4AFF.

import React from "react";
import './SearchPower.css';
import { YMaps, Map, Placemark} from '@pbe/react-yandex-maps';

function App() {
  // 定义用户地理位置
  var getLocationPromise = new Promise((resolve) => {
    navigator.geolocation.getCurrentPosition(async function (position) {
    resolve([position.coords.latitude, position.coords.longitude])
    })
  })
    var [lat, setLat] = React.useState(0)
    var [lng, setLng] = React.useState(0)
  getLocationPromise.then((location) => {
    setLat(location[0])
    setLng(location[1])
  })
  if (lat == 0 && lng == 0) {
    lat = 55.75
    lng = 37.57 }

  // 创建地图
  var myMap = React.useMemo(
    () => ({ center: [lat, lng], zoom: 9 })
  );
  
  // 处理标记
  const [imageHref, setImageHref] = React.useState("images/Marks/ZemMark.png");
  const [ImgStyle, setImgStyle] = React.useState()

function changeGeoPosition(newLink) {
    setImageHref(newLink);
    setImgStyle("5px solid #4D4AFF")
}
    return (
      <div className="ContextSP">
        <div className="DivMarks">
        <img className="MarkLeftImage" src="images/Marks/ZemMark.png" onClick={function() {changeGeoPosition("images/Marks/ZemMark.png")}} style={{borderBottom: ImgStyle}}/>
        <img className="MarkImage" src="images/Marks/Redcar1Mark.png" onClick={function() {changeGeoPosition("images/Marks/Redcar1Mark.png")}} style={{borderBottom: ImgStyle}}/>
        <img className="MarkImage" src="images/Marks/Redcar2Mark.png" onClick={function() {changeGeoPosition("images/Marks/Redcar2Mark.png")}} style={{borderBottom: ImgStyle}}/>
        <img className="MarkImage" src="images/Marks/GreencarMark.png" onClick={function() {changeGeoPosition("images/Marks/GreencarMark.png")}} style={{borderBottom: ImgStyle}}/>
        <img className="MarkRightImage" src="images/Marks/YellowcarMark.png" onClick={function() {changeGeoPosition("images/Marks/YellowcarMark.png")}} style={{borderBottom: ImgStyle}}/> 
        </div>
          <YMaps>
          <Map style={{width: '100%', height: '100%', margin: '0 0 10px 0', border: '3px solid #4D4AFF'}} state={myMap}>
            <div id="Prnt">
              <Placemark geometry={[lat, lng]} 
                  options={{
                    iconLayout: 'default#image',
                    iconImageHref: imageHref,
                    iconImageSize: [40, 40],
                    iconImageOffset: [0, 0],
                    iconOffset: [-5, -38]
                  }} id="myPosition"></Placemark>
              </div>
          </Map>
          </YMaps>
        </div>
        )
    }
    export default App;
P粉590428357P粉590428357401 days ago535

reply all(1)I'll reply

  • P粉787806024

    P粉7878060242023-09-15 14:37:24

    You only have one variable called ImgStyle, which applies the style to all images, and its value is set to all onclick events, so they are always styled the same.

    To do it this way, you need 5 separate state variables - one for each image. But I'm assuming you actually only want to display the border on at most one image - the one you just clicked on - in which case you don't need a separate state variable at all. Just calculate the style based on the current imageHref and the actual href of the image:

    function hasBorder(href) {
      return href === imageHref;
    }

    Then apply it for each image (only an example is shown below, but it should be obvious how to apply to other images):

    <img className="MarkLeftImage" src="images/Marks/ZemMark.png" onClick={function() {changeGeoPosition("images/Marks/ZemMark.png")}} style={hasBorder("images/Marks/ZemMark.png") ? {borderBottom: "5px solid #4D4AFF" } : {}}/>

    You can also simplify this process further by creating an href string array and iterating through the map function to generate each img tag.

    reply
    0
  • Cancelreply