Notice
Recent Posts
Recent Comments
«   2024/07   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
Tags more
Archives
Today
Total
관리 메뉴

HYEWON JUNG의 개발일지

20231116 TIL Fan Letter -4 버튼클릭 시 색 변경, 이미지 디폴트 지정, useContext 이용하기 본문

개발일지

20231116 TIL Fan Letter -4 버튼클릭 시 색 변경, 이미지 디폴트 지정, useContext 이용하기

혜won 2023. 11. 17. 05:03

목표

  • styled component 적용 
  • 이미지 디폴트 넣기
  • drilling 리팩토링 후 context 넘어가기

새로 알게 된것/ 오늘의 코드

이게 맞는진 모르겠으나 css를 모두 styled components로 바꾸기긴 했는디.. 잘은 모르것다.. 잘 활용은 못하는 것 같다. 조건부 스타일링 한 부분만 적고 넘어가겠다.

 

이때까지 필터 버튼을 눌러도 버튼에는 변화가 생기지 않았는데 조건부 스타일링으로 바꿔주었다. 

내가쓴 방법은 필터 버튼 과 비슷하게 구현을 했는데  4개의 버튼에 할당한 state를 선언 하고 초기값을 white 안눌렸을 때 색으로 두고 onclick때마다 set을 할 수 있도록 하는 것이다. 

 

header에 포함이 되어있기에 Header 컴포넌트에서 진행했다!

const CategoryBtnStyle = styled.button`
    border: 2px solid greenyellow;
    border-radius: 10px;
    background-color: ${props => props.btnColor};
    padding: 5px 10px 5px 10px;
    margin: 8px;
   `

 

props 조건부로 받을 수 있도록 만들기

state 만들기

  const [allbtnColor, setAllbtnColor] = useState("white")
  const [idolbtnColor, setIdolbtnColor] = useState("white")
  const [actorbtnColor, setActorbtnColor] = useState("white")
  const [singerbtnColor, setSingerbtnColor] = useState("white")

 

온클릭 넣기

  const allBtnClickColorhandler = () => {
    setAllbtnColor('greenyellow')
    setIdolbtnColor('white')
    setActorbtnColor('white')
    setSingerbtnColor('white')
  }
  const IdolBtnClickColorhandler = () => {
    setAllbtnColor('white')
    setIdolbtnColor('greenyellow')
    setActorbtnColor('white')
    setSingerbtnColor('white')
  }
  const ActorBtnClickColorhandler = () => {
    setAllbtnColor('white')
    setIdolbtnColor('white')
    setActorbtnColor('greenyellow')
    setSingerbtnColor('white')
  }
  const SingerBtnClickColorhandler = () => {
    setAllbtnColor('white')
    setIdolbtnColor('white')
    setActorbtnColor('white')
    setSingerbtnColor('greenyellow')
  }


<CategoryBtn btnColor={allbtnColor} onClick={() => {
  setAllLettersShown(true)
  setIdolLettersShown(false)
  setSingerLettersShown(false)
  setActorLettersShown(false)
  allBtnClickColorhandler()
}}>전체</CategoryBtnStyle>
<CategoryBtnStyle btnColor={idolbtnColor} onClick={() => {
  setAllLettersShown(false)
  setIdolLettersShown(true)
  setSingerLettersShown(false)
  setActorLettersShown(false)
  IdolBtnClickColorhandler()
}}>아이돌</CategoryBtnStyle>
<CategoryBtnStyle btnColor={singerbtnColor} onClick={() => {
  setAllLettersShown(false)
  setIdolLettersShown(false)
  setSingerLettersShown(true)
  setActorLettersShown(false)
  SingerBtnClickColorhandler()
}}>솔로가수</CategoryBtnStyle>
<CategoryBtnStyle btnColor={actorbtnColor} onClick={() => {
  setAllLettersShown(false)
  setIdolLettersShown(false)
  setSingerLettersShown(false)
  setActorLettersShown(true)
  ActorBtnClickColorhandler()
}}>배우</CategoryBtnStyle>

 

버튼에 기존에 필터 기능이있기때문에 밑에 함수 실행으로 추가해준다. 

굳이 함수로 안만들고 진행해도 문제는 없을 것이다.

        <CategoryBtnStyle btnColor={allbtnColor} onClick={() => {
          setAllLettersShown(true)
          setIdolLettersShown(false)
          setSingerLettersShown(false)
          setActorLettersShown(false)
          setAllbtnColor('greenyellow')
          setIdolbtnColor('white')
          setActorbtnColor('white')
          setSingerbtnColor('white')
        }}>전체</CategoryBtnStyle>

이렇게..?  오 그럼 저 필터도 함수로 만들 순 있겠구나 js와jsx 부분중 어디가 간결한게 좋을가? 엇 함수 하나로 필터랑 색깔 바꾸기 다 담아야지

import React, { useState } from 'react'
import styled from 'styled-components'

const HeaderStyle = styled.header`
  background-color: #e0ffbd;
  height: 150px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 20px;
  font-size: 40px;
  font-weight: 800;
  padding-top: 100px;
`
const ButtonBoxStyle = styled.div`
    border: 3px solid greenyellow;
    border-radius: 20px;
    width: 400px;
    display: flex;
    justify-content: center;
    background-color: white;
  `
const CategoryBtnStyle = styled.button`
    border: 2px solid greenyellow;
    border-radius: 10px;
    background-color: ${props => props.btnColor};
    padding: 5px 10px 5px 10px;
    margin: 8px;
   `

function Header({ setIdolLettersShown, setActorLettersShown, setSingerLettersShown, setAllLettersShown }) {

  const [allbtnColor, setAllbtnColor] = useState("white")
  const [idolbtnColor, setIdolbtnColor] = useState("white")
  const [actorbtnColor, setActorbtnColor] = useState("white")
  const [singerbtnColor, setSingerbtnColor] = useState("white")


  const allBtnClickColorhandler = () => {
    setAllbtnColor('greenyellow')
    setIdolbtnColor('white')
    setActorbtnColor('white')
    setSingerbtnColor('white')
    setAllLettersShown(true)
    setIdolLettersShown(false)
    setSingerLettersShown(false)
    setActorLettersShown(false)
  }
  const IdolBtnClickColorhandler = () => {
    setAllbtnColor('white')
    setIdolbtnColor('greenyellow')
    setActorbtnColor('white')
    setSingerbtnColor('white')
    setAllLettersShown(false)
    setIdolLettersShown(true)
    setSingerLettersShown(false)
    setActorLettersShown(false)
  }
  const ActorBtnClickColorhandler = () => {
    setAllbtnColor('white')
    setIdolbtnColor('white')
    setActorbtnColor('greenyellow')
    setSingerbtnColor('white')
    setAllLettersShown(false)
    setIdolLettersShown(false)
    setSingerLettersShown(false)
    setActorLettersShown(true)

  }
  const SingerBtnClickColorhandler = () => {
    setAllbtnColor('white')
    setIdolbtnColor('white')
    setActorbtnColor('white')
    setSingerbtnColor('greenyellow')
    setAllLettersShown(false)
    setIdolLettersShown(false)
    setSingerLettersShown(true)
    setActorLettersShown(false)
  }
  return (
    <HeaderStyle>
      <h1>팬명록</h1>

      <ButtonBoxStyle>
        <CategoryBtnStyle btnColor={allbtnColor} onClick={allBtnClickColorhandler}>전체</CategoryBtnStyle>
        <CategoryBtnStyle btnColor={idolbtnColor} onClick={IdolBtnClickColorhandler}>아이돌</CategoryBtnStyle>
        <CategoryBtnStyle btnColor={singerbtnColor} onClick={SingerBtnClickColorhandler}>솔로가수</CategoryBtnStyle>
        <CategoryBtnStyle btnColor={actorbtnColor} onClick={ActorBtnClickColorhandler}>배우</CategoryBtnStyle>

      </ButtonBoxStyle>
    </HeaderStyle>
  )
}

export default Header

그닥 좋은 코드라는 생각은 안들지만.. 우선 기능구현을 해낸것에 ... 의의를 두고 내일 튜터님찾아가기..

 

이미지 디폴트 적용하기

import defaultAvarta from'assets/defaultAvarta.png'

import를 임의의 이름으로 해와서

        "createdAt": `${years}-${month + 1}-${day} ${hours}:${minutes}`,
        "nickname": nickname,
        "avatar": defaultAvarta,
        "content": content,
        "writedTo": writedTo,
        "id": uuid(),
        "isEdit": false

그 이름으로 넣어주면된다

 

Context로 변경하기

지금 drilling 상황

엄청 많은 것이 있는 것은 아니지만 공통적으로 letters와 setLetters가 props drilling을 하고 있는 것을 알 수 있다. 

Home, LetterBox, Router에는 쓰이지 않는데 전달을 위해 받고 있기 때문이다. 

context를 이용해서  전역에서 사용할 수 있도록 해주자.

 

shared 폴더에 Context.js를 추가한 후 뿌려주기

import { createContext } from "react";

export const Context = createContext(null)

2023.11.09 - [React] - React Hooks useContext, reactMemo, useCallback, useMemo

 

React Hooks useContext, reactMemo, useCallback, useMemo

useContext (useContext API) context 는 전역적으로 사용되는 어떤것을 말할 때 많이 쓰이는 용어다. 일반적을 데이터를 넘겨줄 때 부모에서 자식컴포넘트로 props를 통해서 데이터를 내려주곤 했는데 이

hyewonjung-coding.tistory.com

사용법은 참고하면서 했다.

필요없던 부분에서 props 받던 곳은 다 지우고  필요한 부분에서만 가져와줬다. 다 가져오긴 좀 비효율이니 하나만 가져오겠다

 

Letters.jsx

import { useContext } from 'react'
import { Context } from 'shared/Context'

function Letters({writedTo}) {
  const navigate = useNavigate();
  const contextData = useContext(Context)

  return (
    <div>
      {contextData.letters
        .filter((L) => {
          return writedTo.includes(L.writedTo)
        })
        .map((letter) => {
          return (
            <LetterStyle key={letter.id} onClick={() => { navigate(`/detail/${letter.id}`) }}>
              <div>
                <LetterImg src={letter.avatar} alt=''></LetterImg>
              </div>
              <div>
                <p>{letter.nickname}</p>
                <TimeStyle>{letter.createdAt}</TimeStyle>
                {letter.content.length <= 45 ? <ContentStyle>{letter.content}</ContentStyle> : <ContentStyle>{letter.content.slice(0, 35)}...</ContentStyle>}
              </div>
            </LetterStyle>
          )
        })}

    </div>
  )
}

export default Letters

 

이렇게 사용해주면된다!

오잉.. 금방끝나네.. 

한 10분 걸렸나?

 

목표 달성여부

  • styled component 적용 
  • 이미지 디폴트 넣기 => 계속 안되더라니 import방법이 틀렸었다.
  • drilling 리팩토링 후 context 넘어가기

내일 목표

  • context  => 해버림
  • redux
  • 렌더링 최적화하기