Components

🍕 Components Types

Stateless Functional Components

interface AppProps {
    name: string;
}

// Stateless Functional Component
const App: React.SFC<AppProps> = ({ name }) => 
                                      (<h1>Hello {name}!</h1>);

Statefull Class Components

interface ComponentProps {
  name: string;
  onClick(): void;
}

// Statefull Class Component
class ComponentName extends React.Component<ComponentProps>{
  render() {
      return (<h1>Hello {this.props.name}!</h1>)
  }
}

Component Internal State

this.state

Define and initialize the state

class CounterState {
  count: number = 0;
}

class CounterName extends React.Component<CounterProps, CounterState>{
  constructor(props: CounterProps) {
    super(props);
    this.state = new CounterState();
  }

  render() {
      return (<button>Count: {this.state.count}</button>)
  }
}

Changing component state

class Counter extends React.Component<CounterProps, CounterState>{
  constructor(props: CounterProps){/**/}
  
  increment() {
    this.setState({
      count: this.state.count + 1
    });
  }

  render() {
      return (<button onClick={this.increment.bind(this)}>{this.state.count}</button>)
  }
}

State derived from previous state

class Counter extends React.Component<CounterProps, CounterState>{
  ...
  increment() {
    this.setState((prevState) => {
      return {
        count: prevState + 1
      }
    });
  }
  ...
}

State derived from previous state

class Counter extends React.Component<CounterProps, CounterState>{
  ...
  increment() {
    this.setState((prevState) => ({
        count: prevState + 1
    }));
  }
  ...
}


Components Lifecycle

Mount
Mount
Update
Mount
Update
Unmount
class Component<P, S> {
    constructor(props: Readonly<P>): void {/**/}
    static getDerivedStateFromProps?: (nextProps: Readonly<P>, prevState: S) => Partial<S> | null {/**/}
    
    shouldComponentUpdate?(nextProps: Readonly<P>, nextState: Readonly<S>, nextContext: any): boolean {/**/}
    
    render(): ReactNode {/**/}
    getSnapshotBeforeUpdate?(prevProps: Readonly<P>, prevState: Readonly<S>): SS | null {/**/}
    
    componentDidMount?(): void {/**/}
    componentDidUpdate?(prevProps: Readonly<P>, prevState: Readonly<S>, snapshot?: SS): void {/**/}
    componentWillUnmount?(): void {/**/}
}

🎨 Browser rendering

Webkit (Safari)
Gecko (Firefox)

DOM Tree

Render Tree

Layout

Paint

  • Each DOM change goes through all steps starting from the creation of the DOM tree to painting.
  • Each manipulation can trigger layout changes, tree modifications and rendering.

⚡️ React Virtual DOM

  • Groups multiple DOM manipulations
  • Keeps track of changed nodes

Additional resources

🛠 Try it

1. Create statefull App component that compose all game components
2. App component state holds:
- shuffled cards list
- matched cards
- selected card 1
- selected card 2
- moves
- elapsed time
3. Update the App state as user interacts with the game.