React: State Topics/Notes
Tags: react, devops, beginners, javascript
Published: 2021-10-19 17:37:25

* Hello Again! Honestly great to be back. Pass couple of days consisted of me moving and getting everything set up to work again. 
* Today FreeCodeCamp we're learning about state. Basically consist of any data our application needs to know about, that can change over time. We want our apps to respond to state changes and present an updated UI necessary. 
* We can create state in React component by declaring state property on the component class in its constructor.
* Don't forget it must be set to a JavaScript object.
* Ex: 
```React
this.state = {

}
```
* We have access to the state object throughout the life of our component. we can either update it, render it in our UI, and pass it as props to child components. We should create a class component by extending React.Component in order to create state like this.
* Ex:
```React
class StateComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      name: "Randy" 
    }
  }
  render() {
    return (
      <div>
        <h1>{this.state.name}</h1>
      </div>
    );
  }
};
```
* Here we have initialized the component and assigned my name to a property of name.

##Rendering state in the user Interface
* After defining state, we can display it in the UI that is rendered. If the component is stateful, then it will always have access to the data in state in its render() method.
* You can access the data with `this.state`.
* If however you want to access a state value within the return of the render method, it's important to enclose the value in curly braces.
* Code:
```React
class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      name: "Randy Rivera"
    }
  }
  render() {
    return (
      <div>
        <h1> {this.state.name}</h1>
      </div>
    );
  }
};
```
* Here MyComponent is already stateful, we defined an h1 tag in the component's render method which renders the value of name from the component's state. It's important to know that h1 renders the value from state and nothing more. In JSX any code we write with curly braces will be treated as JavaScript.
* Its state is local to that component, unless you pass state data to a child component as props.
* Another way to access state in a component is in the render() method, before the return statement, you can write JavaScript directly. Example, you could declare functions, access data from state or props.
* Ex:
```JSX
class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      name: 'Randy Rivera'
    }
  }
  render() {
    const name = this.state.name;
    return (
      <div>
        <h1>{name}</h1>
      </div>
    );
  }
};

```
* Remember, you need to use the JSX syntax (curly braces for JavaScript) in the return statement.

##Notes:
* state is a really powerful feature in React. It allows you to track important data in your app and render a UI in response to changes in this data. If your data changes, your UI will change.

##Set State With this.setState
* There's a way to change the component's state. React provides a method for updating component state called `setState`. You call the `setState` method within your component class like this: `this.setState()`, passing in an object with key-value pairs.
* Ex: 
```React
this.setState({
  name: "Randy WaitForIt Rivera"
})
```
* Ex:
```React
class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      name: 'Initial State'
    };
    this.handleClick = this.handleClick.bind(this);
  }
  handleClick() {
    this.setState({
      name: "Randy WaitForIt Rivera!"
    })

  }
  render() {
    return (
      <div>
        <button onClick={this.handleClick}>Click Me</button>
        <h1>{this.state.name}</h1>
      </div>
    );
  }
};
```
* When you click the button, watch the rendered state update. 

## Bind 'this' to a Class Method
* You can also define methods for your component class.
Generally it needs to use the `this` keyword so it can access properties on the class (like state and props) inside the scope of the method.
* One of the ways to do this is bind `this` in the constructor so `this` becomes bound to the class methods when the component is initialized. In the above section it used this.handleClick = this.handleClick.bind(this) for its handleClick method in the constructor. 
* Ex:
```React
class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      text: "PS5 Players Unite!"
    };
    this.handleClick = this.handleClick.bind(this)
  }
  handleClick() {
    this.setState({
      text: "PS5 And PC Players Unite!"
    });
  }
  render() {
    return (
      <div>
        <button onClick = {this.handleClick}>Click Me</button>
        <h1>{this.state.text}</h1>
      </div>
    );
  }
};
```
* Here Theres a state that keeps track of the text. There's a mthod which allows you to set the text to `PS5 And PC Players Unite!`. Although the method didn't work because it used this keyword that is undefined. I fixed it by binding this to the handleClick() method in the component's constuctor.
* After that I added a click handler to the button element method.
* When completed you will be able to click the button and see `PS5 And PC Players Unite!`

##Using State to toggle an Element
* There are probably times that you might need to know the previous state when updating the state. Since in React they're multiple setState() calls into a single update. This means you can't rely on the previous value of this.state or this.props when calculating the next value. So your code should look like this.
```React
this.setState((state, props) => ({
  counter: state.counter + props.increment
}));
```
* Here I passed setState a function that allows you to access state and props. Using a function with setState guarantees you are working with the most current values of state and props.

* Or maybe you want to use a form without props and just state.
```React
this.setState(state => ({
  counter: state.counter + 1
}));
```
* FreeCodeCamp provided us with MyComponent which has a visibility property that is initialized to false. The render method returns one view if the value of visibility is true, and a different view if it is false.
* But there is no way of updating the visibility property in the component's state. The value should toggle back and forth between true and false. We need topPass a function to setState to define this method so that the state of visibility toggles to the opposite value when the method is called. 
```React
class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      visibility: false
    };
    
    this.toggleVisibility = this.toggleVisibility.bind(this)
    


  }
  toggleVisibility() {
  this.setState(state => {
    if (state.visibility === true) {
      return { visibility: false } 
    } else {
      return { visibility: true }
    }
    
  })
  }

  render() {
    if (this.state.visibility) {
      return (
        <div>
          <button onClick={this.toggleVisibility}>Click Me</button>
          <h1>Now you see me!</h1>
        </div>
      );
    } else {
      return (
        <div>
          <button onClick={this.toggleVisibility}>Click Me</button>
        </div>
      );
    }
  }
}
```
* Now if you click the button you will see the conditional rendering of the component based on its state.



##Writing a Simple Counter
* The more we learn the more we can design a more complex stateful component by combining the concepts we've been over. Which includes state and writing methods that set state and assigning click handlers to trigger these methods.
* Now FreeCodeCamp wants us to write a method so that the counter value is incremented or decremented by 1 when the right button is clicked. It also wants us to write a reset() method so when the user clicks it, it resets the count to 0.
```React
class Counter extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    };
    // Change code below this line

    // Change code above this line
  }
  // Change code below this line

  // Change code above this line
  render() {
    return (
      <div>
        <button className='inc' onClick={this.increment}>Increment!</button>
        <button className='dec' onClick={this.decrement}>Decrement!</button>
        <button className='reset' onClick={this.reset}>Reset</button>
        <h1>Current Count: {this.state.count}</h1>
      </div>
    );
  }
};
```

*Answer:

```React
class Counter extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    };
    this.increment = this.increment.bind(this)
    this.decrement = this.decrement.bind(this)
    this.reset = this.reset.bind(this)

  
  }
  
  increment() {
    this.setState(state => ({
      count: state.count + 1
    }))
  }

  decrement() {
    this.setState(state => ({
      count: state.count - 1
    }))
  }

  reset() {
    this.setState(state => ({
     count: 0
    }))
  }

  render() {
    return (
      <div>
        <button className='inc' onClick={this.increment}>Increment!</button>
        <button className='dec' onClick={this.decrement}>Decrement!</button>
        <button className='reset' onClick={this.reset}>Reset</button>
        <h1>Current Count: {this.state.count}</h1>
      </div>
    );
  }
};
```

Larson, Q., 2019. Frontend Development Libraries. [online] Freecodecamp.org. Available at: https://www.freecodecamp.org/learn/front-end-development-libraries/react