2

I have a functional react-typescript component which receives a click handler that is firing correctly, however, the component does not update after click event.

i.e:

// for reasons out of the scope of this question, 
// this component should be functional

const Heroes: React.SFC<{}> = () => {
  // for fututre reasons, these variables must leave within this component
  const thor = "isHero";
  const hulk = "isHero";

  function appendSpan() {
    console.log(thor === hulk);
    return thor === hulk ? <span>yes</span> : <span>no</span>;
  }

  return <p onClick={appendSpan}>Are they both heroes?</p>;
};

function App() {
  return (
    <div className="App">
      <Heroes />
    </div>
  );
}

If I'd call the method immediately i.e <p>Are they both heroes? {appendSpan()}</p>

The <span> is appended accordingly, However, the same isn't true for the onClick scenario.

Could you please help me understand what I am missing here?

Here's the code sandbox

3
  • 1
    React rerenders on state and prop changes. appendSpan updates neither. You probably want to pass your callback to your Heroes component so the app can update something and pass the updated something in as a prop to be rendered. Commented Jan 16, 2019 at 3:16
  • I'm still green on the React land, cld you please provide me an example om how to solve the above? Commented Jan 16, 2019 at 3:18
  • 1
    the function returns a value sure, but what is it supposed to do with that value? insert it into the DOM somewhere? Commented Jan 16, 2019 at 3:18

3 Answers 3

3

You can change the Heroes component to a stateful component instead and update the state on click or use Hooks

Update for tsx

class Heroes extends React.Component <{}, any> {
    // for fututre reasons, these variables must leave within this component
    private thor = "isHero";
    private hulk = "isHero";

    constructor(props) {
      super(props);
      this.state = {
        showButton: false
      };
    }

    appendSpan() {
      // update the state to show the button
      this.setState({
        showButton: true
      });
    }

    render() {
      const { showButton } = this.state;
      let button = this.thor === this.hulk ? <span> yes </span> : <span>no</span > ;
      return ( <p onClick={() => this.appendSpan()}> Are they both heroes ? 
        { showButton ? button : '' } 
        </p>);
      }
}

function App() {
  return ( <div className = "App" >
      <Heroes/>
    </div>
  );
}

Another update with react Hooks, introduced in React v16.8.0-alpha.0

// import useState hooks
import { useState } from 'react';

const Heroes: React.SFC<any> = () => {
  // for fututre reasons, these variables must leave within this component
  const thor = "isHero";
  const hulk = "isHero";
  
  // declare a new state variable flag and the update function setFlag
  const [flag, setFlag] = useState(false);
  
  let button = thor === hulk ? <span> yes </span> : <span> no </span >;

  return (<p onClick={() => setFlag(true)}>Are they both heroes?
    {flag ? button : ''}
  </p>);
};

function App() {
  return (
    <div className="App">
      <Heroes />
    </div>
  );
}

created a sandbox here for the implementation with react hooks.

Sign up to request clarification or add additional context in comments.

5 Comments

Thanks a lot for the example. Is a class-based component the only way around this? Could I solve this while still keeping it a functional component?
@NullisTrue the onClick has to trigger something, either prop/state changes. It might be possible to use functional component for either Heroes or App but not both imho, let me try to tinker around in your sandbox
would this be possible with Hooks? I'm just wondering but I'm not sure.
@NullisTrue yes, it will be possible with Hooks, updated the answer above
thank you very much. You've helped and taught me tremendously tonight. I got great things to work and learn this week. I really appreciate your time and help!
0

Because your .appendSpan() returns react dom, but it returns in the scope of onClick event.

When you say <p>Are they both heroes? {appendSpan()}</p>, you are actually tell the app to append the span inside <p> tag...

But onClick={appendSpan}, where do you tell it to append? You didnt tell where to append. So it never makes it to be appended in the DOM tree

1 Comment

could you still provide me with an example on how to learn and implement this properly?
0

The return from appendSpan function needs to be part of what you return in the render function.

You could keep the state on the app component and write a onClick function that changes the state. Pass down the onClick and the state to the Heroes component as props. Depending on the state that you received from props, decide what to render.

React won't "react" from class variables, I see you want to keep the state in the class. Try looking for hooks

Edit 01r3yy2n5v

4 Comments

The only issue for me is that both const thor and hulk needs to exist within the child component. How would I then compare their equality from the parent component via state passed down as props? Could you please provide me an example?
Ferreira Bastos Brag, thank you very much. Forte abraço!
Tranquilo, se puder aceitar minha resposta ajuda 😉
Tive que aceitar a do @Van pq ele postou primeiro. Valeu mais uma vez 🙌

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.