Free React Course
For Beginners

L4 - Building React Component

React For Beginners by Itera

Key Points

  • What is component - quick recap
  • Building "dumb" components - functional and class-based
  • Building "smart" component - functional and class-based
  • What and when to use
  • Components - best practices

Program

  • Create class-based, dumb component - MessageBlock
  • Turn it to the functional component
  • Create smart, class-based component - button with a counter inside
  • Rework previous component to the functional
  • What and when to use
  • Best practices

What is component - quick recap

  • Component - unit of code that encapsulate single, logical functionality
  • Component can be dumb or smart
  • Component accepts props and returns JSX
  • Component can be build as a class or function

Building "dumb" components - functional and class-based

Message block - class-based

Create the type for the props

            type MessageBlockProps = { message: string };
        

Create a class named MessageBlock

            class MessageBlock extends PureComponent<MessageBlockProps> {}
        

Create method render inside the class

class MessageBlock extends PureComponent<MessageBlockProps> {
    render(){}
}
        

Return from the render method some JSX

            class MessageBlock extends PureComponent<MessageBlockProps> {
    render() {
        const { message } = this.props;
        return <div className="ma-message">{message}</div>;
    }
}
            
        

Message block - functional

Create the type for the props 😊

            type MessageBlockProps = { message: string }; 
        

Define a function with correct type

const MessageBlock: FC<MessageBlockProps> = ({ message }) => ();
        

Return from the function some JSX

const MessageBlock: FC<MessageBlockProps> = ({ message }) => (
    <div className="ma-message">{message}</div>
);
          

Very simple! 😊

Building "smart" component - functional and class-based

Class-based button with counter

Define types...

type BtnProps = {};

Write the new class BtnWithCounter

class BtnWithCounter extends PureComponent<BtnProps> {}
        

Create new object named state and put counter equal to 0 inside

class BtnWithCounter extends PureComponent<BtnProps> {
    state = { counter: 0 };
}
        

Write a method that will handle click

handleClick = () => {
    const { counter: oldValue } = this.state;
    const counter = oldValue + 1;
    this.setState({ counter });
    this.props.onAfterChange(counter);
};
        

Write render method that will return btn and counter

render() {
    const { counter } = this.state;
    return (
        <button type="button" onClick={this.handleClick}>
        Clicked {counter} times
        </button>
        );
}
        

How does magic work

State = {counter:0}
⬇️
Render() = 0
⬇️
OnClick
⬇️
SetState({counter: counter+1})
⬇️
Render() = 1

Functional button with counter

Define type

type BtnProps = {
    onAfterChange: (v: number) => void;
};
        

Create a function

const BtnWithCounter: FC<BtnProps> = ({ onAfterChange }) => {
    return <></>
}
        

Setup state

const [counter, setCounter] = useState(0); // setup state
    const BtnWithCounter: FC<BtnProps> = ({ onAfterChange }) => {
    return <></>
}    

Define handler for click

const handleClick = () => {                   // define handler
    const newValue = counter + 1;             // implement logic
    setCounter(newValue);                     // update state 
    onAfterChange(newValue);                  // invoke callback
};
            

Return JSX

return (
    <button type="button" onClick={handleClick}>
        Clicked {counter} times
    </button>
);                        

What and when to use

  • Functional components are great as "dumb" components or small stateful components
  • Class-based components are great for the component with complex logic
  • PureComponent by default also great for performance reasons

How to

  • Create a list?
  • Show an image?

Using map to create a list

const users = ['Maria', 'Andriy', 'Ihor'];
const UserList = () => (
    <ul>
    {users.map((user) => (
        <li key={user}>{user}</li>
    ))}
    </ul>
);
            

Showing an image

import img from './my-image.png';

const Avatar = () => <img src={img} alt="MyPhoto" />;
            

Components - best practices

Law of Demeter

  • Pass to component as less as possible
  • Return from component as less as possible

Single responsibility

In ideal world - the are should be a single reason to change the component

Open-Closed principle

Component should be open for extension, but closed for modification

Home task

  • Add footer to your application
  • Split the application you've built previously into components
  • Create a component named `` which will render `a`. Component should:
  • Be typed
  • Accept custom text
  • Accept custom url
  • Accept callback that should be invoked before the click
  • Put the new component into the footer
  • When clicked, it should log into the console next text: `redirecting user to the next {link}` where `{link}` should be a's href

Useful links

Join me

Twitter
GitHub