react - custom hook ์‚ฌ์šฉํ•˜๊ธฐ

์ปดํฌ๋จผํŠธ์˜ ๋กœ์ง์„ ์žฌ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ ๊ณ ์ฐจ ์ปดํฌ๋„ŒํŠธ(Higher-Order Components)๋ฅผ ์‚ฌ์šฉํ•ด์™”์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ custom hook์œผ๋กœ ๋” ๊ฐ„ํŽธํ•˜๊ฒŒ ์ƒํƒœ๊ด€๋ฆฌ ๋กœ์ง์„ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ1) React ๊ณต์‹๋ฌธ์„œ ์˜ˆ์ œ

// CommentList.js
class CommentList extends React.Component {
  constructor(props) {
    super(props);
    this.handleChange = this.handleChange.bind(this);
    this.state = {
      comments: DataSource.getComments()
    };
  }

  componentDidMount() {
    DataSource.addChangeListener(this.handleChange);
  }

  componentWillUnmount() {
    DataSource.removeChangeListener(this.handleChange);
  }

  handleChange() {
    this.setState({
      comments: DataSource.getComments()
    });
  }

  render() {
    return (
      <div>
        {this.state.comments.map((comment) => (
          <Comment comment={comment} key={comment.id} />
        ))}
      </div>
    );
  }
}

์œ„ ์ฝ”๋“œ๋Š” ์™ธ๋ถ€๋กœ๋ถ€ํ„ฐ ๋ฐ์ดํ„ฐ๋ฅผ ๊ตฌ๋…ํ•˜์—ฌ ๋Œ“๊ธ€๋ชฉ๋ก์„ ๋ Œ๋”๋งํ•˜๋Š” CommentList ์ปดํฌ๋จผํŠธ ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋ฐ‘์—๋Š” ๋ธ”๋กœ๊ทธ ํฌ์ŠคํŠธ ๊ตฌ๋…์„ ํ•˜๊ธฐ์œ„ํ•ด ๋น„์Šทํ•œ ํŒจํ„ด์œผ๋กœ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ž‘์„ฑํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

// BlogPost.js
class BlogPost extends React.Component {
  constructor(props) {
    super(props);
    this.handleChange = this.handleChange.bind(this);
    this.state = {
      blogPost: DataSource.getBlogPost(props.id)
    };
  }

  componentDidMount() {
    DataSource.addChangeListener(this.handleChange);
  }

  componentWillUnmount() {
    DataSource.removeChangeListener(this.handleChange);
  }

  handleChange() {
    this.setState({
      blogPost: DataSource.getBlogPost(this.props.id)
    });
  }

  render() {
    return <TextBlock text={this.state.blogPost} />;
  }
}

์œ„ ์ƒํ™ฉ์€ HOC๋ฅผ ์‚ฌ์šฉํ•ด ์ค‘๋ณต์„ ์ œ๊ฑฐ ํ•  ์ˆ˜๋„ ์žˆ์ง€๋งŒ custom hook ์„ ๋งŒ๋“ค์–ด์„œ ์ฒ˜๋ฆฌ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. custom hook์œผ๋กœ ์ฒ˜๋ฆฌ์‹œ HOC๋ณด๋‹ค ์žฅ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

HOC์™€ ๋น„๊ตํ–ˆ์„๋•Œ custom hook์˜ ์žฅ์ 

  1. Wrapper Hell์„ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  2. ๋”์šฑ ๊ฐ„ํŽธํ•˜๊ฒŒ ์ƒํƒœ๊ด€๋ฆฌ ๋กœ์ง์„ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

HOC๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๊ฒฐ๊ตญ์€ ํ•˜๋‚˜์˜ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ƒ์„ฑํ•ด์„œ ๊ฐ์‹ธ์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ๊ฐ์‹ธ๋‹ค ๋ณด๋ฉด wrapper hell์ด ๋ฐœ์ƒํ•˜๊ฒŒ ๋ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  hook์„ ๋งŒ๋“ค๋ฉด ๋ณ„ ๋‹ค๋ฅธ ์ž‘์—…์—†์ด React ํ•จ์ˆ˜์•ˆ์—์„œ๋Š” ํŽธํ•˜๊ฒŒ ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•ด ์ง‘๋‹ˆ๋‹ค. ์ด์ œ custom hook์„ ๋งŒ๋“ค์–ด์„œ ์œ„ ์˜ˆ์ œ๋ฅผ ์ข€ ๋” ํŽธํ•˜๊ฒŒ ๋งŒ๋“ค์–ด ๋ด…์‹œ๋‹ค.

custom hook ์‚ฌ์šฉ

// SubscribeData.js
function useSubscribeData({ fetchData, id }) {
  const [data, setData] = React.useState(null);

  const handleChange = React.useCallback(() => {
    setData(fetchData(id));
  }, [fetchData, id])

  React.useEffect(() => {
    DataSource.addChangeListener(handleChange);

    return () => {
      DataSource.removeChangeListener(handleChange);
    }
  }, [handleChange])

  React.useEffect(() => {
    setData(fetchData(id));
  }, [fetchData, id])

  return data;
}

useSubscribeData.defaultProps = {
  id: '',
}

์œ„ ์ฒ˜๋Ÿผ custom hooks์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค. custom hooks ์•ˆ์—์„œ๋„ ๋˜‘๊ฐ™์ด useEffect๋‚˜ useState๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด์ œ ๋งŒ๋“  SubscribeData hook์„ ์‚ฌ์šฉํ•ด ๋ด…์‹œ๋‹ค. ๋ฆฌํ„ด์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๋‚ผ ์ˆ˜๋„ ์žˆ์ง€๋งŒ ํ•จ์ˆ˜๋ฅผ returnํ•ด์„œ state๋ฅผ ๋ณ€๊ฒฝ ํ•˜๋Š”๊ฒƒ๋„ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

// CommentList.js
const CommentList = () => {
  const fetchData = React.useCallback(() => {
    return DataSource.getComments();
  }, []);

  const comments = useSubscribeData({
    fetchData: fetchData
  });

  return (
    <div>
      {comments.map(comment => (
        <div comment={comment} key={comment.id} />
      ))}
    </div>
  );
};

// BlogList.js
const BlogList = ({ id }) => {
  const fetchData = React.useCallback(() => {
    return DataSource.getBlogPost(id);
  }, [id]);

  const post = useSubscribeData({
    fetchData: fetchData,
    id: id
  });

  return <div>this is post!!</div>;
};

์ด์ œ ์†์‰ฝ๊ฒŒ component๋ฅผ ์ถ”๊ฐ€ํ•˜์ง€ ์•Š์•„๋„ ์ƒํƒœ๊ด€๋ฆฌ ๋กœ์ง์€ ์ปดํฌ๋„ŒํŠธ๋ผ๋ฆฌ ๊ณต์œ ๊ฐ€ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

์ฐธ๊ณ ํ•œ ์ž๋ฃŒ

react ๊ณต์‹๋ฌธ์„œ


@๊น€๋Œ€์™„
์•ˆ๋…•ํ•˜์„ธ์š”

AboutGitHub