简体   繁体   English

将一个react class组件重写为功能组件

[英]Rewrite a react class component as a functional component

I try to use a library Tick , but it only has a demo , which is written in React class component.我尝试使用库Tick ,但它只有一个demo ,它是用 React class 组件编写的。

import React from "react";
import Tick from "@pqina/flip";
import "@pqina/flip/dist/flip.min.css";

export default class Flip extends React.Component {
  constructor(props) {
    super(props);
    this._tickRef = React.createRef();
  }

  componentDidMount() {
    this._tickInstance = Tick.DOM.create(this._tickRef.current, {
      value: this.props.value
    });
  }

  componentDidUpdate() {
    if (!this._tickInstance) return;
    this._tickInstance.value = this.props.value;
  }

  componentWillUnmount() {
    if (!this._tickInstance) return;
    Tick.DOM.destroy(this._tickRef.current);
  }

  render() {
    return (
      <div ref={this._tickRef} className="tick">
        <div data-repeat="true" aria-hidden="true">
          <span data-view="flip">Tick</span>
        </div>
      </div>
    );
  }
}

I'd like to use the library as a Hook component, the following code is what I rewritten:我想将该库用作 Hook 组件,以下代码是我重写的:

import Tick from "@pqina/flip";
import "@pqina/flip/dist/flip.min.css";
import React, { useEffect, useRef, useState } from 'react';

interface IFilpProps {
    value: number
}

const Filp: React.FC<IFilpProps> = (props) => {

    const ref = useRef<HTMLDivElement>(null);
    const [tickInstance, setTickInstance] = useState<any>();

    useEffect(() => {
        setTickInstance(Tick.DOM.create(ref.current, {
            value: props.value
        }));
        return () => {
            Tick.DOM.destroy(ref.current);
        }
    }, []);

    useEffect(() => {
        tickInstance?.value && (tickInstance.value = props.value);
    }, [props.value])

    return <div ref={ref} className="tick">
        <div data-repeat="true" aria-hidden="true">
            <span data-view="flip">Tick</span>
        </div>
    </div>
}

outside the component, I have a button, every time I click it adds one:在组件之外,我有一个按钮,每次单击它都会添加一个:

const [flipSecond, setFlipSecond] = useState<number>(0);
// Omit some not important code
<Flip value={flipSecond}></Flip>
<button onClick={() => setFlipSecond(flipSecond+1)}>+1</button>

The demo which uses class component works fine, but my hook code can't work normally: when I click the '+1' button, the Flip component won't plus 1. Could you help me find out the the reason? 使用class组件的demo可以正常工作,但是我的钩子代码不能正常工作:当我点击'+1'按钮时,Flip组件不会加1。你能帮我找出原因吗?

You should use a ref instead of state to store tickInstance .您应该使用 ref 而不是 state 来存储tickInstance In general if you want to replace variables that used to be stored in the constructor before, it is recommended now to be stored as refs when rewriting class based components to functional.一般来说,如果你想替换之前存储在构造函数中的变量,现在建议在将基于 class 的组件重写为函数时存储为 refs。

export default function Flip({value}) {
  const tickRef = React.useRef();
  let tickInstance = React.useRef()


  useEffect(()=>{
    tickInstance.current = Tick.DOM.create(tickRef.current, {
      value
    });

    return () =>  Tick.DOM.destroy(tickRef.current);
  },[])

  useEffect(()=>{
    if (!tickInstance.current) return;
    tickInstance.current.value = value;
  },[value])

  return (
    <div ref={tickRef} className="tick">
    <div data-repeat="true" aria-hidden="true">
      <span data-view="flip">Tick</span>
    </div>
  </div>
  )
}

Demo 演示

This is a rewrite for the historic counter这是对历史计数器的重写

Eg.例如。 Counts the time passed since the start of the millenium in years, months, days, hours, minutes and seconds.以年、月、日、小时、分钟和秒为单位计算自千禧年开始以来经过的时间。

The main thing to take away from here is the use of useRef() and how we are using it when creating the tickInstance with Tick.DOM.create()从这里要带走的主要内容是useRef()的使用以及我们在使用Tick.DOM.create()创建tickInstance时如何使用它

const FlipClock = () => {

  const tickRef = useRef();

  useEffect(() => {
   const tickInstance = Tick.DOM.create(tickRef.current);

   Tick.count.up("2000-01-01T00:00:00", 
   {format: ["y", "M", "d", "h", "m", "s"],})
   .onupdate = (value) => {
  tickInstance.value = value;
 };
});

return (
    <div ref={tickRef} style={{ fontSize: "3rem" }}>
      <div data-repeat="true" aria-hidden="true">
        <span data-view="flip">Tick</span>
      </div>
   </div>
 );
};

export default FlipClock;

Demo演示

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM