ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • React Pattern
    React 2021. 11. 30. 23:36

    이 글은 React를 이용한 개발 중 가장 많이 사용되는 패턴을 정리하기 위해 작성하였습니다.



    < Pattern 1 >

    A stateful, parent component passes down its state to a stateless, child component.

     

    < Step >
    1. Build a stateful Component Class
    2. Build a stateless Component Class
    3. Pass a Component's state

     

    Example)

    import React from 'react';
    import ReactDOM from 'react-dom';
    import { Child } from './Child';
    
    class Parent extends React.Component {
      constructor(props) {
        super(props);
        this.state = { name: 'Frarthur'}
      }
    
      render() {
        return <Child name={this.state.name} />;
     }
    }
    
    ReactDOM.render(<Parent />, document.getElementById('app'))

    : Parent(Stateful) Component

    import React from 'react';
    import ReactDOM from 'react-dom';
    
    export class Child extends React.Component {
      constructor(props) {
        super(props);
      }
    
      render() {
        return <h1>Hey, my name is {this.props.name}</h1>;
     }
    }

    : Child(Stateless) Component

     

    +. Don't Update props

    • A React component should use props to store information that can be changed, but can only be changed by a different component.
    • A React component should use state to store information that the component itself can change.

     

    ex)

    import React from 'react';
    
    class Bad extends React.Component {
      render() {
        this.props.message = 'yo'; // NOOOOOOOOOOOOOO!!!
        return <h1>{this.props.message}</h1>;
      }
    }

     

     


    < Pattern 2 >

    Child components update their parent's State

     

    < Step >
    1. Define an state-changing method on the Parent component (use this.setState or useState)
    2. Pass the state-changing method down to Child component
    3. Receive the Event Handler

     

    Example)

    import React from 'react';
    import ReactDOM from 'react-dom';
    import { Child } from './Child';
    
    class Parent extends React.Component {
      constructor(props) {
        super(props);
        this.changeName = this.changeName.bind(this);
        this.state = { name: 'Frarthur' };
      }
    
      changeName(newName) {
        this.setState({
          name: newName
        })
      }
    
      render() {
        return <Child name={this.state.name} onChange={this.changeName} />
      }
    }
    
    ReactDOM.render(
    	<Parent />,
    	document.getElementById('app')
    );

    : Parent(Stateful) Component

    import React from 'react';
    
    export class Child extends React.Component {
      constructor(props) {
      super(props);
      this.handleChange = this.handleChange.bind(this);
    }
    
      handleChange(e) {
        const name = e.target.value;
        this.props.onChange(name);
      }
    
      render() {
        return (
          <div>
            <h1>
              Hey my name is {this.props.name}!
            </h1>
            <select id="great-names" onChange={this.handleChange}>
              <option value="Frarthur">
                Frarthur
              </option>
    
              <option value="Gromulus">
                Gromulus
              </option>
    
              <option value="Thinkpiece">
                Thinkpiece
              </option>
            </select>
          </div>
        );
      }
    }

    : Child(Stateless) Component

     

     


    < Pattern 3 >

    A Child component updates its parent's state, the parent passes that state to a sibling component.

     

    one component for displaying the name, and a different component for allowing a user to change the name.
    -> One to Display, Another to Change

     

    Example)

    import React from 'react';
    import ReactDOM from 'react-dom';
    import { Child } from './Child';
    import { Sibling } from './Sibling';
    
    class Parent extends React.Component {
      constructor(props) {
        super(props);
        this.state = { name: 'Frarthur' };
        this.changeName = this.changeName.bind(this);
      }
    
      changeName(newName) {
        this.setState({
          name: newName
        });
      }
    
      render() {
        return (
          <div>
            <Child onChange={this.changeName} />
            <Sibling name={this.state.name} />
          </div>
        );
      }
    }
    
    ReactDOM.render(
      <Parent />,
      document.getElementById('app')
    );

    : Parent(Stateful) Component

    import React from 'react';
    
    export class Child extends React.Component {
      constructor(props) {
        super(props);
    
        this.handleChange = this.handleChange.bind(this);
      }
    
      handleChange(e) {
        const name = e.target.value;
        this.props.onChange(name);
      }
    
      render() {
        return (
          <div>
            <select
              id="great-names"
              onChange={this.handleChange}>
              <option value="Frarthur">Frarthur</option>
              <option value="Gromulus">Gromulus</option>
              <option value="Thinkpiece">Thinkpiece</option>
            </select>
          </div>
        );
      }
    }

    : Child(Stateless) Component

    import React from 'react';
    
    export class Sibling extends React.Component {
      render() {
        const name = this.props.name;
        return (
          <div>
            <h1>Hey, my name is {name}!</h1>
            <h2>Don't you think {name} is the prettiest name ever?</h2>
            <h2>Sure am glad that my parents picked {name}!</h2>
          </div>
        );
      }
    }

    : Sibling(Stateless) Component

     

     


    < Pattern 4 >

    Separating container components from presentational components.

    When one component has too many responsibilities.
    That is, If a component has to have state, make calculations based on props, or manage any other complex logic, then that component shouldn’t also have to render HTML-like JSX.

     

    < Step >
    1. Identifiy that the original component was handling both calculations/logic and presentation/rendering
    2. Copy the original component to a new container(or presentational) component file.
    3. Remove all of the presentation/rendering code from the container component.
    4. Remove all of the calculation/logic code from the presentational component.
    5. Accesse the presentational component from withing the container using import, export
    6. Edit the container's render( ) method to render the presentational component with proper props

     

    import React from 'react';
    import ReactDOM from 'react-dom';
    
    const GUINEAPATHS = [
      'https://content.codecademy.com/courses/React/react_photo-guineapig-1.jpg',
      'https://content.codecademy.com/courses/React/react_photo-guineapig-2.jpg',
      'https://content.codecademy.com/courses/React/react_photo-guineapig-3.jpg',
      'https://content.codecademy.com/courses/React/react_photo-guineapig-4.jpg'
    ];
    
    export class GuineaPigs extends React.Component {
      constructor(props) {
        super(props);
        this.state = { currentGP: 0 };
        this.interval = null;
        this.nextGP = this.nextGP.bind(this);
      }
    
      nextGP() {
        let current = this.state.currentGP;
        let next = ++current % GUINEAPATHS.length;
        this.setState({ currentGP: next });
      }
    
      componentDidMount() {
        this.interval = setInterval(this.nextGP, 5000);
      }
    
      componentWillUnmount() {
        clearInterval(this.interval);
      }
    
      render() {
        let src = GUINEAPATHS[this.state.currentGP];
        return (
          <div>
            <h1>Cute Guinea Pigs</h1>
            <img src={src} />
          </div>
        );
      }
    }
    
    ReactDOM.render(
      <GuineaPigs />, 
      document.getElementById('app')
    );

    : Original Component

    import React from 'react';
    
    const GUINEAPATHS = [
      'https://content.codecademy.com/courses/React/react_photo-guineapig-1.jpg',
      'https://content.codecademy.com/courses/React/react_photo-guineapig-2.jpg',
      'https://content.codecademy.com/courses/React/react_photo-guineapig-3.jpg',
      'https://content.codecademy.com/courses/React/react_photo-guineapig-4.jpg'
    ];
    export class GuineaPigs extends React.Component {
      render() {
        let src = this.props.src;
        return (
          <div>
            <h1>Cute Guinea Pigs</h1>
            <img src={src} />
          </div>
        );
      }
    }

    : Presentational Component

    import React from 'react';
    import ReactDOM from 'react-dom';
    import { GuineaPigs } from '../components/GuineaPigs';
    
    const GUINEAPATHS = [
      'https://content.codecademy.com/courses/React/react_photo-guineapig-1.jpg',
      'https://content.codecademy.com/courses/React/react_photo-guineapig-2.jpg',
      'https://content.codecademy.com/courses/React/react_photo-guineapig-3.jpg',
      'https://content.codecademy.com/courses/React/react_photo-guineapig-4.jpg'
    ];
    
    class GuineaPigsContainer extends React.Component {
      constructor(props) {
        super(props);
        this.state = { currentGP: 0 };
        this.interval = null;
        this.nextGP = this.nextGP.bind(this);
      }
    
      nextGP() {
        let current = this.state.currentGP;
        let next = ++current % GUINEAPATHS.length;
        this.setState({ currentGP: next });
      }
    
      componentDidMount() {
        this.interval = setInterval(this.nextGP, 5000);
      }
    
      componentWillUnmount() {
        clearInterval(this.interval);
      }
    
      render() { 
        const src = GUINEAPATHS[this.state.currentGP]; 
        return <GuineaPigs src={src} />;
      }
    }
    
    ReactDOM.render(
      <GuineaPigsContainer />, 
      document.getElementById('app')
    );

    : Container Component

    'React' 카테고리의 다른 글

    Function Components  (0) 2021.12.05
    Component Lifecycle  (0) 2021.12.02
    React Useful Tools  (0) 2021.11.24
    State  (0) 2021.10.30
    this.props  (0) 2021.10.30

    댓글

Designed by Tistory.