๐Ÿค“ ๋ฆฌ์•กํŠธ ์˜ต์…”๋„ ์ฒด์ด๋‹ ์—ฐ์‚ฐ์ž, useSelector, useCallback, ์กฐ๊ฑด๋ถ€ ๋ Œ๋”๋ง (ํ† ๊ธ€ ๊ธฐ๋Šฅ Toggle)

leehyunjuยท2021๋…„ 5์›” 3์ผ
0

์ธํ”„๋Ÿฐ ์ œ๋กœ์ดˆ๋‹˜์˜ NodeBrid ๊ฐ•์˜ ๋“ฃ๊ณ  ๊ณต๋ถ€ํ•œ ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.

๐ŸŒผ reducer๋ฅผ useSelector๋ฅผ ํ†ตํ•ด ๋ถˆ๋Ÿฌ์˜ค๊ธฐ.

const PostCard = ({ post }) => {
  //์žˆ๋‚˜์—†๋‚˜ ์˜๋ฌธ์ผ๋•Œ ?. ๋ฅผ ์‚ฌ์šฉ (?. = ์‹ ์ƒ๋ฌธ๋ฒ•)
  const id = useSelector((state) => state.user.me?.id);

props์— post๋ผ๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ ๋“ค์–ด์žˆ๋‹ค. ์ด ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ์ƒ๋‹จ์—๋Š” import PropTypes from "prop-types"; ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๊ณ  ๋งจ ํ•˜๋‹จ์—๋Š”

PostCard.propTypes = {
  post: PropTypes.shape({
    id: PropTypes.number,
    User: PropTypes.object,
    content: PropTypes.string,
    createdAt: PropTypes.object,
    Comments: PropTypes.arrayOf(PropTypes.any),
    Images: PropTypes.arrayOf(PropTypes.any),
  }),
};

๐ŸŒผ ์˜ต์…”๋„ ์ฒด์ด๋‹ ์—ฐ์‚ฐ์ž

  const id = useSelector((state) => state.user.me?.id);

useSelector๋Š” import { useSelector } from "react-redux"; ์ด๋ ‡๊ฒŒ ๋ถˆ๋Ÿฌ์˜ค๊ณ  ์ด๋Š” ๋ฆฌ์•กํŠธ ๋ฆฌ๋•์Šค๊ฐ€ ์ œ๊ณตํ•œ๋‹ค.

์—ฌ๊ธฐ์„œ ์“ฐ์ธ ?. ๋Š” ์ด๋ฒˆ์— ์ƒˆ๋กœ์ƒ๊ธด ๋ฌธ๋ฒ•์œผ๋กœ ๋ฌด์Šจ๋œป์„ ์˜๋ฏธํ•˜๋ƒ๋ฉด, me.id๊ฐ€ ์žˆ์œผ๋ฉด id๊ฐ€ ๋“ค์–ด๊ฐ€๊ณ  ์—†์œผ๋ฉด undefined๋กœ ๋ฐ”๊ฟ”์ฃผ๋Š” ์˜ต์…”๋„ ์ฒด์ด๋‹ ์—ฐ์‚ฐ์ž๋‹ค. ์ด๊ฒŒ ์—†์—ˆ๋”๋ผ๋ฉด

  const id = useSelector((state) => state.user.me && state.user.me.id);

์ด๋ ‡๊ฒŒ && ์—ฐ์‚ฐ์ž๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ฝ”๋“œ๋Ÿ‰์ด ๊ธธ์–ด์ง€๊ฒŒ ํ•˜๋Š” ๋ฐฉ๋ฒ•๋„ ์žˆ๋‹ค.ใ…Ž ์žˆ๋‚˜ ์—†๋‚˜ ์˜์‹ฌ๋˜๋Š” ๋ถ€๋ถ„์—๋Š” ์˜ต์…”๋„ ์ฒด์ด๋‹์„ ์‚ฌ์šฉํ•˜๋ฉด ์ข€ ๋” ํŽธํ•˜๊ฒŒ ์“ธ ์ˆ˜ ์žˆ์Œ!

๐ŸŒผ toggle ๊ธฐ๋Šฅ์„ ๋™์ž‘ (useState์™€ useCallback)

toggle ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•ด๋ณด๊ณ  ์‹ถ์„ ๋•Œ๋Š”, useState๋กœ ํ˜„์žฌ ์ƒํƒœ์™€ ๋ฐ”๋€” ์ƒํƒœ๋ฅผ ์ง€์ •ํ•ด ์ค˜์•ผํ•œ๋‹ค. (์ƒ๋‹จ์— ์ž„ํดํŠธ ์‹œ์ผœ์ฃผ๋Š” ๊ฑฐ ์žŠ์ง€๋ง๊ธฐ) ๊ทธ๋ฆฌ๊ณ  ์ฒซ ์ƒํƒœ๋Š” ํ† ๊ธ€๊ธฐ๋Šฅ์„ ๋„ฃ๊ธฐ ์ „์˜ ์ƒํƒœ๋กœ ๋ณด์—ฌ์•ผ๋˜๊ธฐ ๋•Œ๋ฌธ์— false๋กœ ํ•ด์คฌ๋‹ค. ํ† ๊ธ€ ํ•  ์‹œ ์–ด๋–ป๊ฒŒ ๋ณ€ํ™”๋ฅผ ์ค„ ๊ฒƒ์ธ์ง€์— ๋Œ€ํ•œ ๊ฒƒ์€ useCallback์„ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

 const [liked, setLiked] = useState(false);
  const [commentFormOpened, setCommentFormOpened] = useState(false);

  const onToggleLike = useCallback(() => {
    setLiked((prev) => !prev);
  }, []);

  const onToggleComment = useCallback(() => {
    setCommentFormOpened((prev) => !prev);
  }, []);

๐ŸŒŸ toggle ํ•  ๋•Œ, ๋ฐ”๋€ ์ƒํƒœ๋ฅผ useCallback ํ†ตํ•ด ํ‘œํ˜„ํ•ด ์ค€๋‹ค. ์ด๋•Œ ์กฐ๊ฑด์€ ํ† ๊ธ€๊ธฐ๋Šฅ์ด๋‹ˆ on,off๋ฅผ ๊ตฌํ˜„ํ•ด ์ค˜์•ผ๋˜๊ธฐ ๋•Œ๋ฌธ์— false๋Š” true๋กœ true๋Š” false๋กœ ๋งŒ๋“ค์–ด ์ฃผ๋ ค๋ฉด ์œ„ ์ฝ”๋“œ์ฒ˜๋Ÿผ prev๋ฅผ ์‚ฌ์šฉํ•ด์ฃผ๋ฉด ๋œ๋‹ค. ๐ŸŒŸ

๐ŸŒผ ์กฐ๊ฑด์‹ ๋ Œ๋”๋ง

return (
    <div>
      <Card
        style={{ marginBottom: "20px" }}
        cover={post.Images[0] && <PostImages images={post.Images} />}
        actions={[
          <RetweetOutlined key="retweet" />,
          liked ? (
            <HeartTwoTone
              twoToneColor="#eb2f96"
              key="heart"
              onClick={onToggleLike}
            />
          ) : (
            <HeartOutlined key="heart" onClick={onToggleLike} />
          ),
          <MessageOutlined key="message" onClick={onToggleComment} />,
          <Popover
            key="ellipsis"
            content={
              <Button.Group>
                {id && post.User.id === id ? (
                  <>
                    <Button>์ˆ˜์ •</Button>
                    <Button type="denger">์‚ญ์ œ</Button>
                  </>
                ) : (
                  <Button>์‹ ๊ณ </Button>
                )}
              </Button.Group>
            }
          >
            <EllipsisOutlined />
          </Popover>,
        ]}
      >
        {/* ๊ฒŒ์‹œ๊ธ€ */}
        <Card.Meta
          avatar={<Avatar>{post.User.nickname[0]}</Avatar>}
          title={post.User.nickname}
          description={post.content}
        />
      </Card>

์กฐ๊ฑด 1. ๋ฒ„ํŠผ ๋ˆŒ๋ €์„ ๋•Œ ์กฐ๊ฑด์‹ ๋‹ฌ๊ธฐ

<Card
        style={{ marginBottom: "20px" }}
        cover={post.Images[0] && <PostImages images={post.Images} />}
        actions={[
          <RetweetOutlined key="retweet" />,
          liked ? (
            <HeartTwoTone
              twoToneColor="#eb2f96"
              key="heart"
              onClick={onToggleLike}
            />
          ) : (
            <HeartOutlined key="heart" onClick={onToggleLike} />
          ),
          <MessageOutlined key="message" onClick={onToggleComment} />,

๋‚ด์šฉ๋ฌผ์„ ๊ฐ์‹ธ๊ณ  ์žˆ๋Š” ์ปดํฌ๋„ŒํŠธ์— cover๋Š” post ์•ˆ์— ์ด๋ฏธ์ง€๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ, PostImages๋ผ๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ฐ€์ ธ์˜ค๊ธฐ. ๋ฒ„ํŠผ์€ ์ด 4๊ฐœ๋ฅผ ๋„ฃ์„ ๊ฒƒ์ธ๋ฐ actions ์•ˆ์—๋‹ค๊ฐ€ ์—ฌ๋Ÿฌ๊ฐœ๋‹ˆ๊นŒ ๋ฐฐ์—ด๋กœ ๋„ฃ์–ด์ฃผ๋ฉด ๋œ๋‹ค. ๋จผ์ € [๋ฆฌํŠธ์œ—๋ฒ„ํŠผ, ํ•˜ํŠธ๋ฒ„ํŠผ, ๋ฉ”์‹œ์ง€๋ฒ„ํŠผ,popover] ์ด๋ ‡๊ฒŒ ํ•˜์˜€๋‹ค. (Popover๋Š” ๋ฐ‘์— ์žˆ์Œ) ๊ทธ๋ฆฌ๊ณ  ๋ฐฐ์—ด์€ ๊ผญ key๊ฐ’์„ ๋„ฃ์–ด์ค˜์•ผ ํ•œ๋‹ค. ์žŠ์ง€๋ง๊ณ  ๊ณ ์œ ์˜ ๊ฐ’์œผ๋กœ ๋„ฃ์–ด์ฃผ๊ธฐ.

ํ•˜ํŠธ ๋ฒ„ํŠผ๊ณผ ๋ฉ”์‹œ์ง€ ๋ฒ„ํŠผ์€ ํ† ๊ธ€ ๊ธฐ๋Šฅ์„ ๋„ฃ์–ด์ค˜์•ผ ๋˜๋Š”๋ฐ, ํ•˜ํŠธ๋ฅผ ๋ˆŒ๋ €์„ ๋•Œ ํˆฌํ†ค์ปฌ๋Ÿฌ๊ฐ€ ๋ณ€๊ฒฝ๋˜๊ฒŒ ์ปดํฌ๋„ŒํŠธ ์•ˆ์— ์Šคํƒ€์ผ ์ ์šฉํ•ด์ฃผ๊ณ  ์•„๋‹ ์‹œ์—๋Š” ๊ทธ๋ƒฅ ํ•˜ํŠธ ์•„์›ƒ๋ผ์ธ๋งŒ ๋ณด์—ฌ์ง€๊ฒŒ ! ํ•˜ํŠธ, ๋ฉ”์‹œ์ง€ ๋ฒ„ํŠผ์€ ๊ฐ™์€ onToggleLike ์ด๋ฒคํŠธ๋ฅผ ์‚ฌ์šฉํ–ˆ๋‹ค.

์กฐ๊ฑด 2. ๋‚ด๊ฐ€ ์ž‘์„ฑํ•œ ๊ธ€์ด๋ฉด ์ˆ˜์ •๊ณผ ์‚ญ์ œ๋ฒ„ํŠผ์ด ๋ณด์ด๊ฒŒ ๋‚ด๊ฐ€ ์ž‘์„ฑํ•œ ๊ธ€์ด ์•„๋‹ˆ๋ฉด ์‹ ๊ณ ๋ฒ„ํŠผ๋งŒ ๋ณด์ด๋„๋ก.

	<Popover
          key="ellipsis"
          content={
            <Button.Group>
              {id && post.User.id === id ? (
                <>
                  <Button>์ˆ˜์ •</Button>
                  <Button type="denger">์‚ญ์ œ</Button>
                </>
              ) : (
                <Button>์‹ ๊ณ </Button>
              )}
            </Button.Group>
          }
        >
          <EllipsisOutlined />
        </Popover>,

opover์ด๋ผ๋Š” ์ปดํฌ๋„ŒํŠธ๋Š” ๋งˆ์šฐ์Šค๋ฅผ ์˜ฌ๋ ค๋†จ์„ ๋•Œ ํŒ์—…์ฐฝ์ด ๋œจ๋Š” ์ปดํฌ๋„ŒํŠธ๋‹ค. ์ด ์ปดํฌ๋„ŒํŠธ์— content๋กœ๋Š” antd์—์„œ ์ œ๊ณตํ•ด์ฃผ๋Š” <Button.Group>์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ–ˆ๋Š”๋ฐ ์กฐ๊ฑด์€ id๊ฐ€ ์žˆ๊ณ  ๋‚ด ์•„์ด๋””๋ž‘ ๊ฒŒ์‹œ๊ธ€ ์ž‘์„ฑ์ž์˜ ์•„์ด๋””๊ฐ€ ๊ฐ™์œผ๋ฉด ๋งˆ์šฐ์Šค๋ฅผ ๋ฒ„ํŠผ์œ„์— ์˜ฌ๋ ค๋†จ์„ ๋•Œ ์ˆ˜์ •๊ณผ ์‚ญ์ œ๋ฒ„ํŠผ์ด ๋ณด์—ฌ์ง€๋„๋ก, ๊ทธ๊ฒŒ ์•„๋‹ˆ๋ผ๋ฉด ์‹ ๊ณ ๋ฒ„ํŠผ๋งŒ ๋ณด์ด๋„๋ก ์กฐ๊ฑด์‹ ๋ Œ๋”๋ง์„ ์„ค์ •ํ•œ ๊ฒƒ์ด๋‹ค.

์กฐ๊ฑด์‹์„ ์‚ฌ์šฉํ•ด์ค„ ๋•Œ๋Š” { } ์ค‘๊ด„ํ˜ธ ์•ˆ์—๋‹ค๊ฐ€ js ์ฒ˜๋Ÿผ ์„ค์ •ํ•ด์ฃผ๊ณ , ํ•˜๋‚˜์˜ ๊ฐ์ฒด๋“ค์€ ( ) ์†Œ๊ด„ํ˜ธ๋กœ ๋ฌถ์–ด์„œ ํ‘œํ˜„ํ•ด์ค€๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์‚ผํ•ญ ์—ฐ์‚ฐ์ž๋ฅผ ์จ์„œ ๋งž์œผ๋ฉด (?) ์ˆ˜์ •์‚ญ์ œ, ๊ทธ๊ฒŒ ์•„๋‹ˆ๋ผ๋ฉด (:) ์‹ ๊ณ ๋ฒ„ํŠผ ๋ณด์ด๊ฒŒ ์™„๋ฃŒ.

์•„๋ฐ”ํƒ€์˜ ๋‹‰๋„ค์ž„ ์ฒซ๊ธ€์ž ๋ฐฐ์—ด๋กœ ์ง€์ •ํ•˜๊ธฐ

<Card.Meta
          avatar={<Avatar>{post.User.nickname[0]}</Avatar>}
          title={post.User.nickname}
          description={post.content}
        />

๊ฒŒ์‹œ๊ธ€ ๋‚ด์šฉ๋ฌผ์€ avatar์— ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋„ฃ๊ณ  post์— User ๋‹‰๋„ค์ž„์˜ ์ฒซ๊ธ€์ž๋งŒ ๋”ฐ์„œ ๋ณด์—ฌ์ง€๊ฒŒ๋” ํ–ˆ๋‹ค.

profile
์•„๋Š‘ํ•œ ๋‡Œ๊ณต๊ฐ„ ๐Ÿง 

0๊ฐœ์˜ ๋Œ“๊ธ€