在React项目中将类组件转换为功能组件(使用React Hooks)

接下来介绍一下如何使用react hooks(react钩子)将类组件转换为功能组件。

说明:react hooks(react钩子)必须在react 16.7版本上运行

react在16.7alpha版本中引入了react hooks(react钩子)的使用,hooks(钩子)是如何工作的?公开了两个新的api来处理状态和生命周期方法(他们是类函数的核心组件),这些api是useState和useEffect,他们有效的处理状态和生命周期方法。

接下来,我们一起来探索两个hooks(钩子)的用法,hooks(钩子)帮助你在功能组件中利用类组件的特性。

接下来通过几个案例来演示一下hooks(钩子)的使用方法:

1.one.js

(1)类组件的原始写法:

import React, { Component } from "react";

class One extends Component {
  state = {
    count: 0
  };
  increase = () => {
    this.setState({ count: this.state.count + 1 });
  };

  render() {
    return (
      <div style={{ marginBottom: "50px" }}>
        <h2>Challenge 1</h2>
        <p>Count is: {this.state.count}</p>
        <button onClick={this.increase}>Increase Count!</button>
      </div>
    );
  }
}

export default One;

(2)使用react hooks(钩子)重写组件

可以看到,我们使用一个状态变量去表示count,它是被用于去构建一个简单的计时器。使用useState钩子我们将把组件重写为一个函数。

import React, { useState } from "react";

const One = () => {
  const [count, setCount] = useState(0);
  return (
    <div style={{ marginBottom: "50px" }}>
      <h2>Challenge 1</h2>
      <p>Count is: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increase Count!</button>
    </div>
  );
};

export default One;

我们可以看到这种方式更加干净简洁,这里我们简单地使用destructured useState钩子将count和setCount的值分配给状态值和分别更改此值的方法。

2.two.js

类似的,从One.js我们只有一个状态变量,这次是一个字符串。

(1)类组件的原始写法

import React, { Component } from "react";

class Two extends Component {
  state = {
    activeUser: "Chris"
  };
  changeUser = () => {
    this.setState({ activeUser: "Bolingo!" });
  };

  render() {
    return (
      <div style={{ marginBottom: "50px" }}>
        <h2>Challenge 2</h2>
        <p>Active User is: {this.state.activeUser}</p>
        <button onClick={this.changeUser}>Change Me!</button>
      </div>
    );
  }
}

export default Two;

(2)使用react hooks(钩子)重写组件

以相似的方式,我们使用useState将状态变量包含是在一个功能组件中,如下所示:

import React, { useState } from "react";

const Two = () => {
  const [activeUser, changeUser] = useState("Chris");
  const newName = () => changeUser("Bolingoli!");

  return (
    <div style={{ marginBottom: "50px" }}>
      <h2>Challenge 2</h2>
      <p>Active User is: {activeUser}</p>
      <button onClick={newName}>Change Me!</button>
    </div>
  );
};

export default Two;

在这个组件中,我们使用从useState解构的changeUser函数创建了一个新函数来处理名称的改变。

3.在three.js中我们来看看多状态值的处理:

(1)类组件的原始写法:

import React, { Component } from "react";

class Three extends Component {
  state = {
    year: 1995,
    type: "Mercedes",
    used: true
  };
  swapCar = () => {
    this.setState({
      year: 2018,
      type: "BMW",
      used: false
    });
  };

  render() {
    return (
      <div style={{ marginBottom: "50px" }}>
        <h2>Challenge 3</h2>
        <h3>Car Spec is:</h3>
        <ul>
          <li>{this.state.type}</li>
          <li>{this.state.year}</li>
          <li>{this.state.used ? "Used Car" : "Brand New!"}</li>
        </ul>
        <button onClick={this.swapCar}>Swap Car!</button>
      </div>
    );
  }
}

export default Three;

(2)使用react hooks(钩子)重写组件

在这个组件中,我们有3个状态变量将在组件中发生改变,对于每个单独的变量useState将被解构多次。有了这个,我们可以一次处理所有的状态变量,并且在渲染时,他们按照列出的顺序调用。

import React, { useState } from "react";

function Three() {
  const [year, changeYear] = useState(1995);
  const [type, changeType] = useState("Mercedes");
  const [used, changeCondition] = useState(true);

  const swapCar = () => {
    changeYear(2018);
    changeType("BMW");
    changeCondition(false);
  };

  return (
    <div style={{ marginBottom: "50px" }}>
      <h2>Challenge 3</h2>
      <h3>Car Spec is:</h3>
      <ul>
        <li>{type}</li>
        <li>{year}</li>
        <li>{used ? "Used Car" : "Brand New!"}</li>
      </ul>
      <button onClick={swapCar}>Swap Car!</button>
    </div>
  );
}

export default Three;

类似,我们创建了一个swapCar函数去处理所有改变。

4.Four.js

(1)类组件原始的写法:

import React, { Component } from "react";

class Four extends Component {
  state = {
    message: "What's happening this week?"
  };

  componentDidMount() {
    setTimeout(() => {
      this.setState({ message: "I only know it's gon be lit!!" });
    }, 5000);
  }

  render() {
    return (
      <div style={{ marginBottom: "50px" }}>
        <h2>Challenge 4</h2>
        <p>Status: {this.state.message}</p>
      </div>
    );
  }
}

export default Four;

(2)使用react hooks(钩子)重写组件:

在这个组件中,componentDidMount被用于组件挂载后5秒去更新一个状态变量的值。这里我们需要useEffect钩子去处理生命周期方法。

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

const Four = () => {
  const [message, newessage] = useState("What's happening this week?");

  useEffect(() => {
    setTimeout(() => {
      newessage("I only know it's gon be lit!!");
    }, 5000);
  }, []);

  return (
    <div style={{ marginBottom: "50px" }}>
      <h2>Challenge 4</h2>
      <p>Status: {message}</p>
    </div>
  );
};

export default Four;

在useEffect中,我们使用setTimeout函数来延迟newMessage方法的执行。注意作为传给useEffect的第二参数传递的空数组,这里允许函数只运行一次(在第一次渲染时)。每次使用数据的值或者数组的值改变的时候。这应该可以让你深入了解如何处理组件中的更新。

5.Five.js

这里我们需要使用三元条件运算符渲染另一个组件的类组件并将其转换为功能组件。

(1)类组件原始的写法:

import React, { Component } from "react";
import Little from "./Little";

class Five extends Component {
  state = {
    showText: true
  };
  showLittle = () => {
    this.setState({ showText: !this.state.showText });
  };

  render() {
    return (
      <div style={{ marginBottom: "50px" }}>
        <h2>Challenge 5</h2>
        <h3>Here below lies little text in a box</h3>
        <button onClick={this.showLittle}>Click to toggle Little</button>
        {this.state.showText ? <Little /> : ""}
      </div>
    );
  }
}

export default Five;

(2)使用react hooks(钩子)重写组件(转换成功能组件):

import React, { useState } from "react";
import Little from "./Little";

const Five = () => {
  const [showText, toggleShowText] = useState(true);

  const showLittle = () => {
    toggleShowText(!showText);
  };

  return (
    <div style={{ marginBottom: "50px" }}>
      <h2>Challenge 5</h2>
      <h3>Here below lies little text in a box</h3>
      <button onClick={showLittle}>Click to toggle Little</button>
      {showText ? <Little /> : ""}
    </div>
  );
};

export default Five;

再次使用useState去创建和更新一个状态值。此外,还导入了一个Little.js组件,并在使用create按钮切换状态后有条件的呈现该组件,让我们看看最后一个组件和它在toggle上的行为。

6.Little.js

我们有一个简单的类组件,它使用componentWillUnmount方法来提醒用户。这只是该方法的一个简单描述,可以在该方法中执行其他操作。

(1)类组件原始的写法:

import React, { Component } from "react";

class Little extends Component {
  componentWillUnmount() {
    alert("Goodbye!!");
  }

  render() {
    return (
      <div style={{ marginBottom: "50px", border: "1px solid black" }}>
        <h5> Hi I'm Little and its nice to meet you!!!</h5>
      </div>
    );
  }
}

export default Little;

(2)将其转换为功能组件,并保留生命周期方法的特性:

import React, { useEffect } from "react";

const Little = () => {
  useEffect(() => {
    return () => {
      alert("Goodbye!!");
    };
  });

  return (
    <div style={{ marginBottom: "50px", border: "1px solid black" }}>
      <h5> Hi I'm Little and its nice to meet you!!!</h5>
    </div>
  );
};

export default Little;

要使用componentWillUnmount方法,只需在useEffect钩子中返回一个函数。现在,一旦我们点击FIve.js中的按钮来切换Little.js,在组建卸载之前,会调用Little.js的useEffect钩子中的函数。

6.总结

在这篇文章中,我们看到了使用React Hooks将类组件转换为功能组件,并保留了这些组件中的状态和生命周期等特性。尝试使用其他生命周期方法,以及在单个组件中同时使用useEffect和useState。

7.参考文献

https://scotch.io/bar-talk/convert-class-components-to-functional-components-in-a-react-project-solution-to-code-challenge-14

文章说明:本篇文章属于本人自己翻译,有些地方翻译的不太好的地方还望指正,谢谢!

  • 7
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值