从零开始使用TS加hooks封装一个简单组件

前言:最近工作刚刚接手React项目,封装一个组件是学习React中最基础的一个部分,那么让我们动手来写一个简单的React组件吧!

1.interface接口定义

首先来看我们要实现的组件效果,如图所示,这是一个简单的展示视频速率的小组件:

image.png
你可以给它设置各种各样的样式,比如经典的深色模式或浅色模式等。
那么它都有哪些属性呢?让我们来看一下 interface.ts 文件:

import { TextStyle, ViewStyle } from 'react-native';

export interface VideoBitProps {
  // 容器样式
  containerStyle: ViewStyle;
  // 文字背景样式
  bitTxtBoxStyle: ViewStyle;
  // 速率单位样式
  unitStyle: TextStyle;
  // 速率样式
  valueStyle: TextStyle;
  // 速率(自定义)
  bitValue: string | undefined;
  // 速率单位
  unit: string;
}
复制代码

主要定义了组件的如下属性:

字段 说明 类型 默认值
unit 速率单位 string kb/s
bitValue 速率(自定义) string undefined
valueStyle 速率样式 TextStyle {}
unitStyle 速率单位样式 TextStyle {}
bitTxtBoxStyle 文字背景样式 ViewStyle {}
containerStyle 容器样式 ViewStyle {}

2.组件实现部分

先来看下整体的代码模块:
index.tsx文件

import React, { useState, useEffect } from 'react';
import _ from 'lodash';
import { View, Text } from 'react-native';
import Styles from './style';
import TYIpcPlayerManager from '../ty-ipc-native';
import { VideoBitProps } from './interface'

const VideoBit: React.FC<VideoBitProps> & {
  defaultProps: Partial<VideoBitProps>;
} = props => {
  const [bitRateValue, setBitRateValue] = useState('');
  const { containerStyle, bitTxtBoxStyle, valueStyle, unitStyle, bitValue, unit } = props;
  let timer = null;
  useEffect(() => {
    convertBitRate();
    return () => {
      clearInterval(timer);
    };
  }, []);
  const convertBitRate = () => {
    getBitValue();
    timer = setInterval(() => {
      getBitValue();
    }, 3000);
  };
  
  const getBitValue = () => {
    TYIpcPlayerManager.getVideoBitRateKBPS()
      .then(data => {
        if (data) {
          const realBit = (+data).toFixed(0);
          setBitRateValue(realBit);
        }
      })
      .catch(err => {
        clearInterval(timer);
      });
  };

  return (
    <View style={[Styles.videoBitContainer, containerStyle]}>
      {(bitRateValue !== undefined) || (bitValue !== undefined )  ? (
        <View style={[Styles.bitTxtBox, bitTxtBoxStyle]}>
          <Text style={[Styles.fontContainer, valueStyle]}>
            {bitRateValue || bitValue}{` `}
            <Text style={[Styles.fontContainer, unitStyle]}>{unit}</Text>
          </Text>
        </View>
      ) : null}
    </View>
  );
};

VideoBit.defaultProps = {
  containerStyle: {},
  bitTxtBoxStyle: {},
  valueStyle: {},
  unitStyle: {},
  unit: 'kb/s',
  bitValue: undefined,
};

export default VideoBit;

复制代码

3.组件使用实例

   const NormalTopRight = () => {
    return (
      <VideoBit
        bitValue="20"
        unit="m/s"
        unitStyle={{ color: 'black' }}
        containerStyle={{ position: 'absolute', left: 20, top: 50 }}
      />
    );
  };
复制代码

4.单元测试

VideoBit.test.ts 文件:

import React from 'react';
import { shallow } from 'enzyme';
import VideoBit from '../index';

describe('VideoBit components', () => {
  it('basic render', () => {
    const wrapper = shallow(
      <VideoBit containerStyle={{ position: 'absolute', right: 0, top: 30 }} />
    );
    expect(wrapper).toMatchSnapshot();
  });
  it('container render', () => {
    const wrapper = shallow(<VideoBit valueStyle={{ color: 'red', fontSize: 24 }} />);
    expect(wrapper).toMatchSnapshot();
  });
  it('bitTxtBox render', () => {
    const wrapper = shallow(<VideoBit bitTxtBoxStyle={{ width: 100, height: 30 }} />);
    expect(wrapper).toMatchSnapshot();
  });
  it('unit render', () => {
    const wrapper = shallow(<VideoBit unitStyle={{ color: 'black' }} />);
    expect(wrapper).toMatchSnapshot();
  });
  it('bit data', () => {
    const wrapper = shallow(<VideoBit bitValue={30} />);
    expect(wrapper).toMatchSnapshot();
  });
  it('unit data', () => {
    const wrapper = shallow(<VideoBit unit="m/s" />);
    expect(wrapper).toMatchSnapshot();
  });
});

复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享