1

I am working on a reacts app and the requirement is to change the image when that row is hovered.

The codesand of the code is attached.

It works fine but the problem is whenever any row is hovered, getData() method fires each time.

How can I stop it fire each time the row is hovered?

https://codesandbox.io/s/react-hooks-usestate-nkymg

Thanks

newbie
  • 530
  • 1
  • 9
  • 36

1 Answers1

1

You can do this by keeping index of hovered row:

class MyTable extends Component {
  img1 = "https://img.icons8.com/material/4ac144/256/camera.png";
  img2 = "https://img.icons8.com/material/4ac144/256/user-male.png";

  constructor(props) {
    super(props);
    this.state = {
      list: ["Pete", "Peter", "John", "Micheal", "Moss", "Abi"],
      hoverIndex: -1
    };
  }

  // Call get data everywhere you want fetch data or do some operatiosn on it
  getData = () => {
    console.log("getData called!");
    this.setState({
      ...this.state,
      list:
        this.state.list.length > 3
          ? this.state.list.slice(0, 3)
          : this.state.list.slice(3, 5)
    });
  };

  handleHover = index => {
    this.setState({ ...this.state, hoverIndex: index });
  };

  handleOut = () => {
    this.setState({ ...this.state, hoverIndex: -1 });
  };

  render() {
    return (
      <div>
        {this.state.list.map((name, index) => (
          <div
            key={name}
            onMouseOver={() => this.handleHover(index)}
            onMouseOut={this.handleOut}
            style={{ display: "flex", justifyContent: "space-around" }}
          >
            <div> {name} </div>
            <div>
              <img
                src={this.state.hoverIndex === index ? this.img2 : this.img1}
                height="30px"
                width="30px"
                alt=""
              />
            </div>
          </div>
        ))}
      </div>
    );
  }
}

And here is my link to the working version demo.

MohammadAmin Mohammadi
  • 1,183
  • 3
  • 14
  • 23
  • This won't work in this case. I also applied this solution but the problem is getData() method is fired on every hover. How can we stop it from firing on every hover. I have to get the data from getData() method (MUST).I updated your codesand, if you could please look at this: https://codesandbox.io/s/react-example-9xcc7 – newbie Jul 15 '20 at 17:51
  • @newbie I've updated so check this code sandbox https://codesandbox.io/s/react-example-zlnpq?file=/index.js, Actually based on your requirement you call getData(), getData will fill new list (it can retrive new list from an api call result, ...) – MohammadAmin Mohammadi Jul 15 '20 at 18:03
  • setTimeout is my simulating function of the way you getData (ex: api call or ...), you should not use setTimout to fill data, it's just an example. And the error is related to items key that are duplicate because I set all of them 'NextItem' you should use your unique keys and identifiers. – MohammadAmin Mohammadi Jul 15 '20 at 18:11
  • Here https://codesandbox.io/s/react-example-eogsf?file=/index.js, Call getData() everywhere you want fetch data or do some operations on it, use this.state.list in rendering. As you can see in example, getData should update state if you do not want to call it in every rerender. – MohammadAmin Mohammadi Jul 15 '20 at 18:27
  • I have updated the example in the question. Can you please have a look. Btw thank you so much for your time – newbie Jul 15 '20 at 20:11
  • @newbie react re-render every time you update state, so if you call getData() in render method of class component or return of functional component, in each render getData() will be called and it's OK. If you don't want getData() to be called in each render, remove it from return part, as an example call it inside useEffect() in functional component. If you need to explain you in details lets continue on discussion. – MohammadAmin Mohammadi Jul 15 '20 at 20:20
  • Actually there is lag on scrolling because of getData() being called every time. I cant move it to useEffect coz then it will only be called once. I have pagination in my app. If I click on page 2, getData() automatically gives data for page 2. What could be the possible solution in this case? – newbie Jul 15 '20 at 20:31
  • useEffect accept a sensitivity list, useEffect(callback, [sensitivity list]), put your page state in sensitivity list, so every time page changes, getData() will be called again. – MohammadAmin Mohammadi Jul 15 '20 at 20:34
  • Ok I got that but then what will come here? `getData().map(...)` – newbie Jul 15 '20 at 20:37
  • Your state variable, in previous example this.state.list, in new example const [list, setList] = useState([]), and in return use list.map(). Note: list is the result after doing operation using getData() on your data and setting result in list using setList(). – MohammadAmin Mohammadi Jul 15 '20 at 20:39
  • Let me try this. Thank a lot for your help btw :) – newbie Jul 15 '20 at 20:53
  • I figured out the problem. The lagging was due to `onMouseEnter` and `onMouseLeave`. It was not due to getData being called every time. I have opened a new question https://stackoverflow.com/questions/62928683/update-img-src-of-hovered-row-using-useref-reactjs . Please have a look – newbie Jul 16 '20 at 07:01