JoShin
JoShin

Reputation: 71

useState set method and state not change in onClick function

A state property is ReactNode, I want to change the property, and then get property value in some onClick functions.

But I find that state property value is not changed.

React code like this:

     import React, { useState, useEffect } from 'react';
     import { Button } from 'antd';

     interface SomeData {
        id?: number;
        content?: React.ReactNode;
     }

     const Test = (): React.ReactElement => {
        const [someData, setSomeData] = useState<SomeData>({});

        const handleClick = (): void => {
            console.log('click event', someData);
        };

        const loadData = (): void => {
            const content = <Button onClick={handleClick}>button#1</Button>;
            setSomeData({ id: 10, content, });
        };

        useEffect(() => { loadData() }, []);


        return (
            <div>
                {someData.content}
                <Button onClick={handleClick}>button#2</Button>
            </div>
        );
     };

when I click button#1, the function handleClick console result is click event {},

and click button#2, console result is click event {id: 10, content: {…}}.

why these two same click events give different results?

Upvotes: 1

Views: 3949

Answers (2)

Jolly
Jolly

Reputation: 1768

Let's see what is happening:

  1. When Test is first rendered, someData is an empty object, thus {someData.content} render nothing.
  2. Your useEffect is called after the first render (because it has an empty dependencies array). In there, it save in someData.content a button, to which a handleClick function is linked.
    NOTE: This handleClick has its own closure, where someData is still an empty object, because the update on someData has not been done, yet.
  3. When you click on button#1, you are calling the handleClick with its closure, in which someData is still an empty object.
  4. Instead, when clicking on button#2, since button#2 is rendered each time, its handleClick closure changes every time the render is done, thus the someData inside these handleClick are updated.

How you could fix this? It depends in what you actually want to do, because I can't understand. You want that, when clicking on button#1, you set the someData.id to 1, and then execute something? Let me know, and I'll try to help you more.

Upvotes: 1

Corentin de Maupeou
Corentin de Maupeou

Reputation: 100

If you want to "activate" your function "handleClick" when you click on your button, you should declare your function is in your function "class".

Example :

import React, { Component, MouseEvent } from 'react';

export class Button extends Component {
  handleClick(event: MouseEvent) {
    event.preventDefault();
    alert(event.currentTarget.tagName); // alerts BUTTON
  }

  render() {
    return <button onClick={this.handleClick}>Click me</button>
  }
}

Source : https://fettblog.eu/typescript-react/events/

Upvotes: 0

Related Questions