2021年6月18日 星期五

[react, component, create] How to create a React component

 How to create a React component

井民全, Jing, mqjing@gmail.com

Here, I'll show you a 3-steps procedure to create a React component. It also includes the responses for the following basic questions:

  1. 如何寫一個 React Component, 當改變它的狀態時, 連帶改變顯示狀態 (How to create a React Component, and How to automatically update the component render state when its state was changed?)

=> use setState.

  1. 如何呼叫 component method, 更改自身的 status, 並且連動改變顯示狀態? (How to invoke a sub-component method to update its state?)
    => use Ref.

  2. 在 typescript function component 形式的 App, 如何使用 React.createRef(). (How to use React.createRef in function component style tsx source?)

=> let mycomonentElement = React.createRef<MyComponent>(); // in tsx function.


Github: https://github.com/jing-tw/lab-react/tree/master/lab/08-my-component/client

Quick

# Step 1: Create React skeleton

npx create-react-app client --template typescript

cd client

yarn build


# Step 2: Create module

vi ./src/mycomonent.tsx

File:./src/mycomponent.tsx

import React from 'react';



class MyComponent extends React.Component {

    // (a) Declare the class property for keep the component state

    state = {           // <<<----- must be 'state'

      mode: 0,       

    }


    // (b)  Declare a method for updating the compoent state 

    public changeMyComponent = (intMode:number) => {

      this.setState({

          mode: intMode

      });

    };


    // (c) Render the component state

    render() {

      return (

        <div>

          <h2>MyComponent component mode = {this.state.mode}.</h2>

        </div>

      );

    }

}


export default MyComponent;



# Use the component

vi: ./src/App.tsx

  1. Import the component

    1. import MyComponent from './mycomponent;

  2. Create reference

    1.  let mycomonentElement = React.createRef<MyComponent>();

  3. Connect to the component (in render)

    1. <MyComponent ref = {mycomonentElement} /> 

  4. Invoke your component method

    1. (mycomonentElement.current as MyComponent).changeMyComponent0(mode++);



Table of Contents

1. Init

2. Create component

2.1. Declare the component

2.2. Another version

3. Usage

3.1. Step 1: Import your component

3.2. Step 2: Link the ref to your component

3.2.1. (a) Create a reference variable

3.2.2. (b) Connect the reference to the component

3.3. Code

4. Install & Build & Run

5. Result

6. Others

6.1. Makeclean

7. References



1. Init

sudo apt-get update

sudo apt-get install -y curl git 

sudo snap install --classic code  # vscode


npx create-react-app client --template typescript

cd client

yarn build


2. Create component

2.1. Declare the component

Declare the component state directly inside the class[1]. Create a new tsx file for you component.

File:./src/mycomponent.tsx

import React from 'react';



class MyComponent extends React.Component {

    // Step 1: Declare the class property for keep the component state

    state = {           // <<<----- must be 'state'

      mode: 0,       

    }


    // Step 2: Declare a method for updating the compoent state 

    public changeMyComponent = (intMode:number) => {

      this.setState({

          mode: intMode

      });

    };


    // Step 3: Render the component state

    render() {

      return (

        <div>

          <h2>MyComponent component mode = {this.state.mode}.</h2>

        </div>

      );

    }

}


export default MyComponent;


2.2. Another version

You can also let the MyComponent component itself builds on empty props and the MyComponentState for the state.

File:./src/mycomponent.tsx

// MyComponent has no properties, but the current state is of type MyComponentState

// The generic parameters in the Component typing allow passing props

// and state. Since we don't have props, we pass an empty object.


type MyComponentState = {

  mode: number,

}

class MyComponent extends React.Component<{}, MyComponentState> {

    // The init function sets the current state. TypeScript will let us know

    // which ones we are allowed to set.

    init() {

      this.setState({

        mode: 0

      });

    }


    public changeMyComponent(intMode:number){

      this.setState({

        mode: intMode

      });

    }


    // Before the component mounts, we initialise our state

    componentWillMount() {

      this.init();

    }

  

    render() {

      return (

        <div>

          <h2>MyComponent component mode = {this.state.mode}.</h2>

        </div>

      );

    }

}


export default MyComponent;




3. Usage 

Use your component and invoke the Ref method to update state

3.1. Step 1: Import your component

import MyComponent from './mycomponent;


3.2. Step 2: Link the ref to your component

3.2.1. (a) Create a reference variable 

let mycomonentElement = React.createRef<MyComponent>();

3.2.2. (b) Connect the reference to the component

return (

    <div className="App">

      <header className="App-header">

        <p>

          <MyComponent ref = {mycomonentElement} /> 

          </p>

      </header>

    </div>

  );



Step 3: Invoke the component method via reference

(mycomonentElement.current as MyComponent).changeMyComponent(2);  


3.3. Code

File: src/App.tsx

import React, { useState } from 'react';

import './App.css';

import Button from '@material-ui/core/Button';


// Step 1: Import your component

import MyComponent from './mycomponent;


let mode:number = 0;

function App() {

  

// Step 2: Link a local reference to you component for invoking method
// (a): Create a reference variable

    let mycomonentElement = React.createRef<MyComponent>();

  

    const updateMap = (k:string,v:any) => {

      setMyMap(new Map(myMap.set(k,v)));

    }


    const onChangeMyComponent = async () => {

        console.log('onChangeMyComponent')

        

// Step 3: Invoke the component method via reference

        (mycomonentElement.current as MyComponent).changeMyComponent0(mode++);     

   }



  return (

    <div className="App">

      <header className="App-header">

        <p>

          <MyComponent ref = {mycomonentElement} />

          <Button onClick= {onChangeMyComponent} variant="contained" color="primary"> Test </Button> 

         </p>

      </header>

    </div>

  );

}


export default App;



4. Install & Build & Run

yarn install

yarn build

yarn start


5. Result

6. Others

6.1. Makeclean

# run clean up

yarn clean

The clean script

File:./package.json     

"clean": "(rm -fr node_modules; rm -fr build; find . -name \"*.js\" -type f|xargs rm -f; find . -name \"*.map\" -type f|xargs rm -f)"



7. References

  1. Where to Initialize State in React, https://daveceddia.com/where-initialize-state-react/

  2. TypeScript and React: Render props and child render props,  https://fettblog.eu/typescript-react/render-props/