Abdulrahman Aly
Abdulrahman Aly

Reputation: 3

How to assign an object's property to another one of it's properties in reactjs?

I am a beginner in reactjs so please bear with me. I am using state and setState in my class component, thing is I want to reference value1,value2 and value3 properties in setState inside the answerIsFalse arrow function as seen in the code below to proposedAnswer and check properties in the same setState instead of currentState because I want to re-assign their values and pass them to state. I tried using this, binding it, and setState.value1 for example but nothing worked.

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';


class App extends Component {
  constructor(){
    super();
    this.setState = this.setState.bind(this);
    const value1 = Math.floor(Math.random() * 100);
    const value2 = Math.floor(Math.random() * 100);
    const value3 = Math.floor(Math.random() * 100);
    const proposedAnswer = Math.floor(Math.random() * 3) + value1 + value2 + value3;
    const numQuestions = 0;
    const numCorrect = 0;
    const check = proposedAnswer === value1 + value2 + value3;
    this.state = {
    value1: value1,
    value2: value2,
    value3: value3,
    proposedAnswer: proposedAnswer,
    numQuestions: numQuestions,
    numCorrect: numCorrect,
    check: check
    };
    
    
  }
  
  
  
  answerIsTrue = () => {
    console.log(this);
    this.setState ((currentState) => ({
        numCorrect: currentState.check ? currentState.numCorrect + 1 : currentState.numCorrect,
        numQuestions: currentState.numQuestions + 1,
        value1: Math.floor(Math.random() * 100),
        value2: Math.floor(Math.random() * 100),
        value3: Math.floor(Math.random() * 100),
        proposedAnswer: Math.floor(Math.random() * 3) + currentState.value1 + currentState.value2 + currentState.value3,
        check: currentState.proposedAnswer === currentState.value1 + currentState.value2 + currentState.value3
        
        
     }))
 }
  
  answerIsFalse = () => {
    console.log(this);
    this.setState ((currentState) => ({
        numCorrect: currentState.check ? currentState.numCorrect : currentState.numCorrect + 1,
        numQuestions: currentState.numQuestions + 1,
        value1: Math.floor(Math.random() * 100),
        value2: Math.floor(Math.random() * 100),
        value3: Math.floor(Math.random() * 100),
        proposedAnswer: Math.floor(Math.random() * 3) + currentState.value1 + currentState.value2 + currentState.value3,
        check: currentState.proposedAnswer === currentState.value1 + currentState.value2 + currentState.value3
        
        
     }))
 }
  
  render() {
    return (
      <div className="App">
        <header className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <h1 className="App-title">ReactND - Coding Practice</h1>
        </header>
        <div className="game">
          <h2>Mental Math</h2>
          <div className="equation">
            <p className="text">{`${this.state.value1} + ${this.state.value2} + ${this.state.value3} = ${this.state.proposedAnswer}`}</p>
          </div>
          <button 
          onClick = {() => this.answerIsTrue()}
          >
          True
          </button>
          <button onClick = {() => this.answerIsFalse()}>
          False
          </button>
          <p className="text">
            Your Score: {this.state.numCorrect}/{this.state.numQuestions}
          </p>
        </div>
      </div>
    );
  }
}

export default App;

Upvotes: 0

Views: 1067

Answers (1)

pazitos10
pazitos10

Reputation: 1709

As I understand, you may be having a misconception of how state and setState works.

The state object is supposed to be immutable, so to "modify" it you need to re-write it every time. For example:

this.state = { age: 25, name: 'John' }

To change the age attribute, you need to use setState() and pass it a new state object.

this.setState({ ...this.state, age: 30}) // {age: 30, name: 'John'}

In this case this.state is giving me access to the current state and all its attributes as they were defined before. To make it more clear:

let newState = { ...this.state, age: 30} 
this.setState(newState) // {age: 30, name: 'John'}

Keep in mind you never have to overwrite this.state but always create a new object and pass it to this.setState() as an argument to be able to modify a component state.

Check out the React's state docs and the spread operator docs.

Also, it seems that your answerIsFalse and answerIsTrue methods share a lot of code and you may want to refactor them. Some of that code can be reused if you put it in its own method, for example:

Math.floor(Math.random() * 100)

You could do something like this:

const getRandomValue = (factor) => {
  return Math.floor(Math.random() * factor)
}

And then use it like this: this.getRandomValue(100) or this.getRandomValue(3) when you need them.

Also, the names are a bit confusing (to me, at least) as may imply that the methods return boolean values but in reality are changing the component's state. I would rename them to something like setAnswerToFalse or something like that.

Upvotes: 1

Related Questions