前端入坑(三)--------react(如何使用state来摆脱静态页面 )

Hey there,

Today we are starting fresh! No longer satisfied by merely saying “hello”, we are launching into exciting new uncharted waters: turning the lights on and off! ? I know, it’s very exciting. I'm excited, anyway.

Over the last couple days you’ve…

  • written a tiny, friendly React app
  • customized that app to be able to greet literally anyone in the entire world
  • hopefully worked through some of the exercises I slaved over (just kidding!) (but seriously. do the exercises.)
  • learned that React isn’t so scary, but it’s also pretty static so far

In today’s lesson we’re going to break away from static pages by learning how to use state.

Our project will be a page where the user can toggle the lights on and off by clicking a button. And by “the lights” I mean the background color (but hey, if you hook this up to an IoT thing in your house, I totally want to hear about it!).

Create the Project

We’re gonna start with a brand new project. Go here: https://codesandbox.io/s/new, erase the contents of index.js, and type this in:

import React from 'react';
import ReactDOM from 'react-dom';
function Room() {
  return (
    <div className="room">the room is lit</div>
  );
}
ReactDOM.render(<Room />, document.getElementById('root'));

This is nothing you haven’t seen before. Just a Room component rendering some JSX. But it’s awfully bright. Let’s turn those lights off.

Make the component stateful

I don’t know if you know this about light switches, but they can be in one of two states: ON and OFF. Conveniently React has a feature called state which allows components to keep track of values that can change – a perfect place to store the state of our light.

In order to add state to our Room component, it has to be turned into a class. In React, function components are stateless. Replace the whole Room function with this class instead:

class Room extends React.Component {
  state = {
    isLit: true
  }
  render() {
    return (
      <div className="room">the room is lit</div>
    );
  }
}

Now that Room is a class, the render method does the same job as our old Room function. Up top is where the state is initialized. This new syntax is all ES6 JavaScript, by the way – not React-specific. (technically the state = { ... } bit is not part of the standard yet, but they’re working hard on that).

Render according to state

Right now, the component works the same as before, because we haven’t changed anything in render. Let’s have it render differently based on the state of the light. Change the <div> to this:

<div className="room">
  the room is {this.state.isLit ? 'lit' : 'dark'}
</div>

As you can see, the light is still on. Now change isLit: true to false. The app will re-render saying “the room is dark.”

Ok so this isn’t very exciting yet; we’ve proved that we can change the display by changing the code ? But we’re getting there.

Change the state when you click the button

Let’s add a button and kick this thing into high gear. Change the div to look like this:

<div className="room">
  the room is {this.state.isLit ? "lit" : "dark"}
  <br />
  <button onClick={this.flipLight}>flip</button>
</div>

So we’ve got a plain old line break with the <br/>, and then a button that says “flip”. When you click the button, it will call the this.flipLight function in the component. And if you’ve been paying attention, we don’t have a flipLight function yet… so let’s add that now.

Above the render() function, and under the state initialization, add this code:

flipLight = () => {
  this.setState({
    isLit: !this.state.isLit
  });
};

Remember how we talked about arrow functions yesterday? This is one of those. Except it’s inside a class, which makes it a member function.

Click the “flip” button now. Does it work? Hooray! We’ll fix the stark white background in a sec, but let’s talk about this setState thing.

How setState works

In the flipLight function, we’re toggling the isLit state true/false depending on what it’s currently set to. You might wonder why we don’t just say this.state.isLit = !this.state.isLit. It’s because the setState function actually has 2 jobs:

  • first it changes the state
  • then it re-renders the component

If you just change this.state directly, React has no way of knowing that it changed, and it won’t re-render. There are more reasons why changing state directly is a bad idea, but for now, just remember to always use this.setState, and don’t modify this.state.anything directly.

We’re alllmost done here, but I promised that the background color would change, and it did not. Yet.

Change the background color

To do that we’re going to use some CSS. Plain old CSS.

In the CodeSandbox editor, hover over the “src” folder on the left and click the “New File” button.

Name it index.css, and paste this in. We don’t need TOO much style here, but we do need some.

html, body, #root, .room {
  height: 100%;
  margin: 0;
}
.lit {
  background-color: white;
  color: black;
}
.dark {
  background-color: black;
  color: white;
}

At the top, we are setting the height of absolutely-freaking-everything to 100%, so that the whole page goes dark instead of just the top 20 pixels. Then we have “lit” and “dark”, which will change the background and text color accordingly.

Now click over to index.js, and at the top of the file, import the CSS file like so:

import "./index.css";

Now all that’s left is to apply the “lit” and “dark” classes to the Room component. Remember how the <div> in Room has the prop className="room"? We need to change that dynamically to “room lit” or “room dark”, depending on the state.

At the top of render (above the return), add a variable for the brightness:

const brightness = this.state.isLit ? "lit" : "dark";	

Then use that variable, plus ES6’s template strings, to change the className on the div. Like this:

<div className={`room ${brightness}`}>

The backticks signify a template string in ES6.

Template strings allow you to insert variables within them, which is what the ${brightness} is doing.

And finally the whole thing is surrounded by single braces because it’s an expression, and because React says so. I’m not sure why React allows you to just pass someProp="string" without the braces but requires the braces when it’s someProp={`template string`}, but it does, so don’t forget them.

Click the button now, and you’ll see that the background color changes along with the text. Woohoo! ?

If your code isn’t working, you can compare it to the final working example here.

Your Turn

Run through these quick exercises to solidify your understanding:

  • Add 2 more buttons: “ON” and “OFF”. Add two corresponding functions (similar to flipLight) to turn the light either ON or OFF depending on which button is clicked, and wire up the buttons to call those functions.
  • Add another piece of state: the room temperature. Initialize it to 72 (or 22 for you Celsius types). Display the current temperature inside render().
  • Add 2 more buttons: “+” and “-”. Then add the corresponding functions that will increase or decrease the temperature by 1 degree when clicked, and wire up the buttons.

Look forward to tomorrow, where we get to fetch REAL data with an API and display it :)

Talk to you then,
Dave

P.S. State is one of the trickier concepts to grok in React.

I put together a Visual Guide to State in React if the concept still seems a bit fuzzy.

My Pure React book dedicates a couple chapters to handling state, including a shopping cart that we build step-by-step.

To make sure you keep getting these emails, please add dave@daveceddia.com to your address book or whitelist us. Want out of the loop? Unsubscribe.

My postal address: P.O. Box 248, Nutting Lake, MA
import React from "react";
import ReactDOM from "react-dom";

import "./index.css";
class Room extends React.Component {
  state = {
    isLit: false,
    isOn: false,
    temperature:22
  };
  flipLight = () => {
    this.setState({
      isLit: !this.state.isLit
    });
  };

  onLight = () => {
    this.setState({
      isOn: !this.state.isOn
    });
  };
  addTem =()=>{
    this.setState({
      temperature: this.state.temperature + 1
    });
  }
  render() {
    const brightness = this.state.isLit ? "lit" :"dark";
    return (
      <div className={`room ${brightness}`}>
        the room is {this.state.isLit ? "lit" : "dark"}
        <br />
        <button onClick={this.flipLight}>flip</button>
        <br />
        the Light is {this.state.isOn ? "on" : "off"}
        <br />
        <button onClick={this.onLight}>isOn</button>
        <br />
        the Temperature is {this.state.temperature}
        <br />
        <button onClick={this.addTem}>+</button> 
      </div>
    );
  }
}
ReactDOM.render(<Room />, document.getElementById("root"));

我的代码 :)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值