From React Class component to Functional component with hooks

React: Magic Eight Ball toy

There are two ways to inject JavaScript code into JSX.

  • Until now, we have injected JavaScript code into JSX using curly braces, { }, in order to access props, pass props, access state, insert comments and style components.
  • From now on, we will also write JavaScript code outside the JSX, directly in the render method, before the return statement. Obviously, when calling the variables from inside the JSX, we will place the variable name inside curly braces.

After building React Counter, React Controlled Input, React Controlled Form, React Toggle Element, this fifteenth episode of the series “From React Class component to Functional component with hooks” example is based on a freeCodeCamp challenge: build the classic 1980’s Magic Eight Ball toy. As usual, we will code it in a class component first and then, in a functional component.

 

Summary

More information about the Magic Eight Ball toy we are going to code

In this small App,

  • the user types his/her question in the input;
  • each time the button is clicked:
    • a random number will be generated and stored as the randomIndex in state,
    • the answer is displayed below the heading “Your answer”,
    • the input is cleaned.
  • the render method has a constant which contains an array of 20 phrases representing the answers found in the classic 1980’s Magic Eight Ball toy;
  • the answer, its index in the array corresponding to the randomIndex calculated, is displayed in a paragraph, under a “Your answer” heading.

Let’s build it in a class component and in a functional component.

Code your Magic Eight Ball toy in a class component

Use Advanced JavaScript in React Render Method:

  • JavaScript constants containing style, array of data… can be inserted in at the top of the render method. (Remark: constants containing style information can be written outside components!)
  • As these constants are not inserted into JSX (into the return statement), they are normally written (not between curly braces).
  • When calling them from the return statement (JSX), the variables are written between curly braces.

Steps to code the Magic Eight Ball toy in a class component

We consider that React as been installed or a new pen as been created on codepen.

  1. Create the HTML file, the element and add it the optimize id attribute to “attach” the React App (Controller component) rendering.
  2. Create the MagicEightBall component.
  3. Declare the local state value properties userInput and randomIndex. Initialize the values with “”.
  4. In the return statement of the render method,
    • write a text type input where the user will type his/her question,
    • assign it a value attribute and pass it the userInput state,
    • assign it an onChange attribute and pass it the method handleChange as handler method,
    • assign it a style attribute and pass it the constant name inputStyle.
  5. Above the render method, declare the handleChange handler method. Pass it the event as argument and set the userInput state with the event target value. Do not forget to bind this method in the constructor.
  6. In the return statement of the render method,
    • write an button element whose text is “Ask the Magic Eight Ball!”,
    • assign it the onClick event and pass it the ask handler method.
  7. Above the render method,
    • declare the ask method;
    • insert a condition based on the userInput state existence and
    • update the randomIndex state using the Math.random() method multiplied by the number of possible Answers (20) and Math.floor() method to round the obtained result,
    • set the userInput state back to an empty string to clear the input and make it ready for the next question.
  8. In the return statement of the render method, add a heading whose text is “Your answer”.
  9. In the return statement of the render method, add a paragraph which will received the answer, one of the item of the array of possibleAnswers.
  10. At the top of the render method, above the return statement, declare a constant whose name is possibleAnswers and contains an array of twenty famous sentences answered by the Magic Eight Ball toy.
  11. At the top of the render method, above the return statement, declare a constant whose name is answer and value is the randomIndex state.
  12. In the return statement, in the paragraph, insert the possibleAnswers constant name between curly braces (JSX here) and give it answer as the random index of the array.
  13. Do not forget to style the input via a constant whose name is inputstyle, placed outside the component.

Find the final code below.

The final code of the Magic Eight Ball toy in a class component

const inputStyle = {
  width: 235,
  margin: 5
};
class MagicEightBall extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      userInput: ”,
      randomIndex: ”
    };
    this.ask = this.ask.bind(this);
    this.handleChange = this.handleChange.bind(this);
  }
  ask() {
    if (this.state.userInput) {
      this.setState({
        randomIndex: Math.floor(Math.random() * 20),
        userInput: ”
      });
    }
  }
  handleChange(event) {
    this.setState({
      userInput: event.target.value
    });
  }
  render() {
    const possibleAnswers = [
      ‘It is certain’,
      ‘It is decidedly so’,
      ‘Without a doubt’,
      ‘Yes, definitely’,
      ‘You may rely on it’,
      ‘As I see it, yes’,
      ‘Outlook good’,
      ‘Yes’,
      ‘Signs point to yes’,
      ‘Reply hazy try again’,
      ‘Ask again later’,
      ‘Better not tell you now’,
      ‘Cannot predict now’,
      ‘Concentrate and ask again’,
      “Don’t count on it”,
      ‘My reply is no’,
      ‘My sources say no’,
      ‘Most likely’,
      ‘Outlook not so good’,
      ‘Very doubtful’
    ];
    const answer = this.state.randomIndex;
    return (
      <div>
        <input
          type=’text’
          value={this.state.userInput}
          onChange={this.handleChange}
          style={inputStyle}
        />
        <br />
        <button onClick={this.ask}>Ask the Magic Eight Ball!</button>
        <br />
        <h3>Answer:</h3>
        <p>
          {possibleAnswers[answer]}
        </p>
      </div>
    );
  }
}

Play with the pen before build the App in a functional component.

Play with the below pen

See the Pen
React tricks: Magic Eight Ball Toy
by Coding-Tricks (@coding-tricks)
on CodePen.

Code your Magic Eight Ball toy in a functional component

Steps to code the Magic Eight Ball toy in a functional component

We consider that React as been installed or a new pen as been created on codepen.

  1. Create the HTML file, the element and add it the optimize id attribute to “attach” the React App (Controller component) rendering.
  2. Import the hook useState.
  3. Create the Controller functional component.
  4. Declare the local state value properties userInput and randomIndex. Declare their updating functions. Initialize the both useState() values with “”.
  5. There is no render method here contrary to the class component. Declare a constant whose name is possibleAnswers and contains an array of twenty famous sentences answered by the Magic Eight Ball toy.
  6. Declare a constant whose name is answer and value is randomIndex.
  7. In the return statement of the function component,
    • write a text type input where the user will type his/her question,
    • assign it a value attribute and pass it userInput as prop,
    • assign it an onChange attribute and pass it the handleChange function as prop,
    • assign it a style attribute and pass it the constant name inputStyle.
  8. Above the return statement, declare the handleChange function. Pass it the event as argument and update the userInput state with the event target value. (No method to bind here.)
  9. In the return statement of the function component,
    • write an button element whose text is “Ask the Magic Eight Ball!”,
    • assign it the onClick event and pass it the ask function.
  10. Above the return statement,
    • declare the ask function;
    • update randomIndex using the Math.random() method multiplied by the number of possible Answers (20) and Math.floor() method to round the obtained result,
    • update userInput back to an empty string to clean the input and make it ready for the next question.
  11. In the return statement, add a heading whose text is “Your answer”.
  12. In the return statement, add a paragraph which will received the answer, one of the item of the array of possibleAnswers.
  13. Above the return statement, declare a constant whose name is answer and value is randomIndex .
  14. In the return statement, in the paragraph, insert the possibleAnswers and give it answer as the random index of the array. Do not forget that possibleAnswers is an array and an index is needed to access the entries. [answer] represents this index.
  15. Do not forget to style the input via a constant whose name is inputstyle, placed outside the component, below the useState hook import.

Find the final code below.

The final code of the Magic Eight Ball toy in a functional component

const { useState } = React;
const inputStyle = {
  width: 235,
  margin: 5
}
const MagicBall = () => {
  const [userInput, setUserInput] = useState(“”);
  const [randomIndex, setRandomIndex] = useState(“”);
  const possibleAnswers = [
    ‘It is certain’,
      ‘It is decidedly so’,
      ‘Without a doubt’,
      ‘Yes, definitely’,
      ‘You may rely on it’,
      ‘As I see it, yes’,
      ‘Outlook good’,
      ‘Yes’,
      ‘Signs point to yes’,
      ‘Reply hazy try again’,
      ‘Ask again later’,
      ‘Better not tell you now’,
      ‘Cannot predict now’,
      ‘Concentrate and ask again’,
      “Don’t count on it”,
      ‘My reply is no’,
      ‘My sources say no’,
      ‘Most likely’,
      ‘Outlook not so good’,
      ‘Very doubtful’
  ];
  const answer = randomIndex;
  const handleChange = (event) => {
    setUserInput(event.target.value)
  };
  const ask = () => {
    setRandomIndex(Math.floor(Math.random() * 20)),
    setUserInput(“”)
  };
  return (
    <div>
      <input
        type=”text”
        value={userInput}
        onChange={handleChange}
        style={inputStyle}
      />
      <button onClick={ask}>Ask the Magic Eight Ball</button>
      <h3>Answer:</h3>
      <p>{possibleAnswers[answer]}</p>
    </div>
  );
}

In the pen inserted below,

Play with the below pen

See the Pen
React tricks: Magic Eight Ball Toy with useState
by Coding-Tricks (@coding-tricks)
on CodePen.

In conclusion

Once again we have passed the challenge: we have built the Magic Eight Ball toy in both class and functional components! Great!

In the next articles we will use conditional rendering…

Haut de page