Get started with TypeScript. Write a React progress bar component

Write it up front

  • If you’ve written react components, this article should be pretty easy for you. Pure plus a little bit of TS knowledge.
  • I describe the process of writing components completely as a learner. Please point out many loose points.

Look at the effect achieved – GIF GIF effect

  • Of course you can click here to try the effect, the effect page
  • You can also open the codeSandbox below to see the source code.

start

  • This is a common UI component, the difficulty is mainly in the design (CSS) above.

  • Requirement: a precision bar carried out step by step, we just need to input parameters, step and total to calculate the percentage and then display ok.


/* * @param step number of steps * @param total total steps * @param showInfo whether to display percentage prompt * @param color can be customized */

Copy the code

With that said, let’s get started

  • I’m going to skip the configuration of the environment, so I’m going to write the code
  • The Node, TS, and Less environments need to be configured

1. Create a progressBar folder under your Componments file. TSX is a special TS file under React. Then continue to add index.tsx and style.less under the progressBar

-- componments
    -- progressBar
        -- index.tsx
        -- style.less
Copy the code

2. Introduce the necessary components first

  • index.tsx
import React, { Component } from 'react';
import * as PropTypes from 'prop-types';
import './style.less';

// Define the interface
export interface IProgressProps{
    
}

/ / define the class
class ProgressBar extends Component<IProgressProps> {}export default ProgressBar;

Copy the code

Key: IProgressProps, named in PASCAL, starts with I, Props stands for this interface parameter support.

3. Based on our analysis of the requirements above, we define the propTypes and defalutProps of the class

export interface IProgressProps {
    // prefixCls classname set uniformly for later stylesprefixCls? : string; step? : number; total? : number; showInfo? : boolean; color? : string; }class ProgressBar extends Component<IProgressProps> {
    // Set the default value
    static defaultProps = {
            prefixCls: 'demo-progress'.step: 2.total: 10.showInfo: false.color: '#FFE103'
        };
    render(){
        return(
            <div>progressBar</div>)}}Copy the code
  • Highlight it. I’ll explain it here. Why ts and prop-types? To constrain the code, the article was posted after a friend pointed out that this repeated. Because just began to write TS also did not notice, and then focus on the relevant information. Turns out you can mix the two.

  • conclusion

Can be validated in typescript, also can be validated only prop – types, also can be validated both mix build, the strict limits and useless. Checking prompts with typescript is a feature of TS, and checking prompts with prop-types is a feature of React.

Key points: The “?” Optional. Number is the type of the interface parameter. You must enter a number, or ts will report an error. Here we can reference the progressBar module to see if it succeeds. If the progressBar is a reality, it is a success.

4, process progress bar UI and text content,render part

/** * @desc handle progressNumber */
const validProgress = (progress: number | undefined) = > {
  // When your argument defines a type such as number, you must call the! Progress, or ts will prompt you with an error.
  if(! progress || progress <0) {
    return 0;
  } else if (progress > 100) {
    return 100;
  }

  return progress;
};

/** * @desc Divide into integers from 0 to 100 * @param step * @param total */
const percentDeal = (step: number | undefined, total: number | undefined) = > {
  if(! step || ! total) {return 0;
  }

  return (step / total) * 100;
};

/** * @param text Percentage display */
const parseIntPrecent = (text: number): string= > `The ${Math.ceil(text)}% `;

class ProgressBar extends Component<IProgressProps> {
   / *... . defaultProps ..... propTypes ...... * /
    render(){
        // Get the required values from this.props first
        // restProps to extend parameters
        const{ prefixCls, step, total, showInfo, color, ... restProps } =this.props;
        
        /** * percent * text tip Displays text * progressInfo info module * porgress main module */
        let percent;
        let text;
        let progressInfo;
        let progress;
        
        // Handle percentage display content
        percent = percentDeal(step, total);
        text = parseIntPrecent(validProgress(percent));
        
        // If true, we create a showInfo module
        if (showInfo) {
            progressInfo = (
                <div className={` ${prefixCls}-show-info`} >
                  <span className={` ${prefixCls}-text`} >{text}</span>
                </div>
            );
        }
        
        // Create a main module to use as a progress bar
        //prefixCls has a unified name
        progress = (
          <div>
            <div className={` ${prefixCls}-outer`} >
              <div className={` ${prefixCls}-inner`} >
                <div className={` ${prefixCls}-bg`} >
                  {progressInfo || null}
                </div>
              </div>
            </div>
          </div>
        );
        
        return (
          <div {. restProps} className={` ${prefixCls} `} >
            {progress}
          </div>); }}Copy the code

Important: Define functions that handle data outside of class, not in Render. Progress bar implementation of many kinds, here is the common three layers, text, background, progress bar, and the outer layer.

5, according to the above GIF design to achieve the style

  • style.less
.tiger-progress { &-outer { width: 100%; display: inline-block; margin-top:30px; margin-right: 0; padding-right: 0; } &-inner { vertical-align: middle; display: inline-block; background: #eeeeee; border-radius: 100px; position: relative; width: 100%; } // leave &-bg background color to represent the length of the progress bar, gray inner background &-line {width: 100%; font-size: inherit; position: relative; } &-text { word-break: normal; width: 2em; text-align: left; font-size: 1em; margin-left: 8px; vertical-align: middle; display: inline-block; white-space: nowrap; line-height: 1; }}Copy the code

Important: // the &-bg color represents the length of the progress bar, and the gray &-inner background represents the total length.

  • Add the code in render to set the length of the progress bar according to the input data calculated by step and total.
 const{ prefixCls, step, total, showInfo, color, ... restProps } =this.props;
        
/** * percent * text tip Displays text * progressInfo info module * porgress main module */
let percent;
let text;
let progressInfo;
let progress;

percent = percentDeal(step, total);
console..log("percent",percent)
// percent: 20

text = parseIntPrecent(validProgress(percent));
console.log('text',text)
// text: 20%

if (showInfo) {
  progressInfo = (
    <div className={` ${prefixCls}-show-info`} >
      <span className={` ${prefixCls}-text`} >{text}</span>
    </div>
  );
}

// color defalutProps defines the default color
// before &-bg set relative position
const fixBgStyle = {
  width: text,
  height: "12px".background: color,
  borderRadius: "100px"
};

progress = (
  <div>
    <div className={` ${prefixCls}-outer`} >
      <div className={` ${prefixCls}-inner`} >
        <div className={` ${prefixCls}-bg`} style={fixBgStyle}>
          {progressInfo || null}
        </div>
      </div>
    </div>
  </div>
);

return (
  <div {. restProps} className="tiger-progress">
    {progress}
  </div>
);

Copy the code

You’re done

  • Is not very simple, but let’s see the effect
  • Codesandbox. IO/s / 940 nq3531… Debug the code

Answer the question: WhytsAlso to useprop-types?

  • Usually when we write a React component, we define a prop-types to validate our class input. The function of the TS interface is, of course, the input to the props.

  • The differences :TypeScrip· type checking is static, prop-types can be checked at run time. If you pass offsetTop=” ABC “, your editor may tell you that the type is wrong, but it will still work in the browser. If you use prop-types, it will prompt you in the browser.

Conclusion: The two types are interchangeable and partially redundant, so we can use typescript without writing prop-types for additional validation.

reference

  • Ts.xcatliu.com/basics/prim…
  • 09 x. Ant. The design/components /…
  • react-bootstrap.github.io/components