18

How to change the button text when someone click on?

Code:

<Button disabled={this.state.disabled}
    type="primary"
    htmlType="submit"
    style={{
      background: '#ff9700',
      fontWeight: 'bold',
      border: 'none',
      float: 'center',
    }}
    loading={this.state.loading}
    onClick={this.enterLoading}
    value="Next"
    id="buttontext"
    onClick="changeText()"
>
    Next 
</Button>
3
  • 5
    use a state variable for that, store the button text in a state variable and update the state using setState to change the button text. Commented Dec 8, 2018 at 17:36
  • @MayankShukla Could you please write code for button Commented Dec 8, 2018 at 17:40
  • 1
    check sample working code. Commented Dec 8, 2018 at 17:41

2 Answers 2

31

Mayank is correct.

Create a variable called "text" (or whatever you choose) and put that instead of "Next".

state = {
  text: "Next"
}

changeText = (text) => {

  this.setState({ text }); 
} 
render() {
const { text } = this.state //destucture state
return (
  <Button 
     onClick={ () => { this.changeText("newtext")}  }> {text} </Button> )...etc

Note: this method will always change the text to "newtext" when you click. You can pass a variable there as well to make it more dynamic.

Hope this helps.

Update: Just saw Mayank comment. That code is essentially what I have. Just a tip you no longer need a constructor and you don't have to bind your methods anymore.

Updated: React Hooks

Same thing but with the useState hook. Instead of calling the state variable text, I am using buttonText to be more explicit. The updated version would look like:

import { useState } from 'react';

const [buttonText, setButtonText] = useState("Next"); //same as creating your state variable where "Next" is the default value for buttonText and setButtonText is the setter function for your state variable instead of setState

const changeText = (text) => setButtonText(text);

return (
  <Button onClick={() => changeText("newText")}>{buttonText}</Button>
)

You can omit the changeText function all together and have this:

return (
    <Button onClick={() => setButtonText("newText")}>{buttonText}</Button>
)

Updated: How to Add Set Timeout

Adding an update to answer a question in the comments: "If I wanted to use a setTimout to bring the button back to the previous text after 1 second where would I add that in?"

There are two ways that comes to mind: add the setTimeout to the changeText function or create an effect that depends on the buttonText.

change text

You can just pop the setTimeout right in this function.

Goes from this

const changeText = (text) => setButtonText(text);

to this

const initialState = "Next";
const [buttonText, setButtonText] = useState(initialState); //same as creating your state variable where "Next" is the default value for buttonText and setButtonText is the setter function for your state variable instead of setState

const changeText = (text) => {
  setButtonText(text);
  setTimeout(() => setButtonText(initialState), [1000])
}

We add the initialState variable as a const to keep track of the "previous text". Since, it should never change we could define it in all caps snake case like const INITIAL_STATE meh your choice.

useEffect

We still need to define that initialState variable, again so we can keep track of the original. Then we can create a useEffect which is a React hook that allows you to "hook" into changes of a variable (that's only a part of useEffect, just enough to get us going here).

We can break the effect down into two essential parts: the body or callback of the effect, what do we want to do when the effect runs and the dependency or what triggers the effect to run. In this case, our callback will be setTimeout and set the button text inside that timeout and our buttonText will trigger the effect.

Here's the effect:

useEffect(() => { 
  if(buttonText !== initialState){
    setTimeout(() => setButtonText(initialState), [1000])
  }
}, [buttonText])

Anytime the state variable buttonText changes this effect will run. We start at

buttonText = initialState // "Next"

the effect runs and checks the if. Since buttonText equals the initialState the conditions evaluates to false and we terminate the callback and the effect.

When the user clicks the button, changeText executes and sets the buttonText state which updates the variable triggering the effect. Now we run that if check again and this time it passes so we execute the setTimeout.

Inside the timeout we are setting state so the effect runs again and this time it fails because we just changed the state back to initialState.

I recommend throwing a debugger in there or some logs to follow the trail

Long winded explanation. Here's what the whole component would look like using the effect approach.

import React, { useState, useEffect } from "react";

const FancyButton = () => {
  const initialState = "Next";
  const [buttonText, setButtonText] = useState("Next"); //same as creating your state variable where "Next" is the default value for buttonText and setButtonText is the setter function for your state variable instead of setState

  // the effect
  useEffect(() => { 
    if(buttonText !== initialState){
      setTimeout(() => setButtonText(initialState), [1000])
    }
  }, [buttonText])

  const changeText = (text) => setButtonText(text);

  return (
    <button type="button" onClick={() => changeText("newText")}>{buttonText}</button>
  )
};

I added the type on the button because that's a good practice. And changed "Button" to "button". You can certainly have any component there you want, this works better for copying and pasting

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

3 Comments

If I wanted to use a setTimout to bring the button back to the previous text after 1 second where would I add that in?
Just seeing this 🙃 @krichey15. You can add the setTimeout in the changeText function.
This is an excellent answer. Thank you. I'm new to react in general and this was clear and concise. If I could give more upvotes, I would. :D
1

Where you wrote "Next", the button text, do this instead:

{this.state.disabled ? 'Disabled...' : 'Next'}

I this will display "Disabled..." when the state.disabled == true, and 'Next' when state.disabled == false.

Comments

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.