WIL (5) (6/6~6/12)

minkyung·2022년 6월 12일
0

WIL

목록 보기
5/7
post-thumbnail

리액트 심화 주차 끝!

기능만 구현하고 페이지 별 상세 기능에서 레이아웃 버튼 설정하는걸 못하고 냈다...
이제 리덕스&파이어베이스 CRUD는 할만 해졌다. 없으면 안되는 정도 ... (진짜 없으면 안되긴함.)

그 기세를 몰아서 보람님이 리덕스 툴킷이 편하다고 하셔서 조금 공부해봤는데
나한텐 구구절절 다 쓰는 리덕스가 더 편하고 직관적으로 느껴졌다 🥲 어이없을 무
이미 리덕스가 익숙한 사람한테는 생략된 부분들이 다 보이지만 나한테는 생략된게 너무 많다고 느껴져서 그런 것 같다.
그래도 리덕스 툴킷도 잘 쓰고 싶어 ❗️❗️❗️❗️❗️



    const [layout, setLayout] = useState(true);


    const layoutCheck = () => {
        if (my_post.layout === "left") {
            return true;
        } else {
            return false;
        }
    }
    
    return (
        <div>
            <h1>메인페이지 입니다.</h1>
            {my_post.map((list, index) => {

                const layoutCheck = () => {
                    if (list[index].layout === "center") {
                        return <div>
                            <ImgPreview src={list.img_url} /> {list.content}
                        </div>
                    } else {
                        return <div>
                            {list.content} <ImgPreview src={list.img_url} />
                        </div>

                    }
                }
    

⬆️ 레이아웃 별로 출력시키고 싶었던 나의 발악 (Main.js)

  1. 포스팅 작성할 때 layout 값에 각각 right, left, center 넣어 놓음

  2. 메인에서 display:grid를 써서 CSS가 아니라 div 노출 순서에 따라 레이아웃 변함

  3. 그래서 layoutCheck 함수를 만들어서 layout이 right,left,center에 따라 return 값에 <div>이미지<div>포스트 내용 넣음.
    나는 이러고 컴포넌트 리턴 안에 함수 넣으면 그대로 return 값에 따라 출력될 줄 알았음 ...

  4. 근데 그냥 layoutCheck 함수 안에 else로 빠져버림 ... 전부 ...

  5. 그래서 my_post.map 돌려서 포스트 출력시키는 곳 안에 if를 넣어봐도 걍 else로 전부 빠져버림

  6. 내가 슬픔에 빠져버림



 return (
        <Container>

            <BackButton onClick={() => history.goBack()}>← 뒤로가기</BackButton><br />

            <h1>수정페이지 입니다.</h1>
            <h3>사진 선택 </h3>
            <input type="file" accept='image/*' onChange={uploadFB} />
            <h3> 레이아웃 고르기</h3>


            <div>
                <input type="radio" name="theme" value="right" 
                onChange={(e) => setLayout({ theme: e.target.value })}/>
                오른쪽에 이미지 왼쪽에 텍스트<br />

                <ImgPreview src={previewImg} layout="0px 0px 0px auto"/>   
                </div>             
                
                <div>
                <input type="radio" name="theme" value="left"
                onChange={(e) => setLayout({ theme: e.target.value })}/>
                왼쪽에 이미지 오른쪽에 텍스트<br />

                <ImgPreview src={previewImg} layout="0px auto 0px 0px"/>
               </div>
               
               <div>
                <input type="radio" name="theme" value="center"
                onChange={(e) => setLayout({ theme: e.target.value })}/>
                하단에 이미지 상단에 텍스트<br />

                <ImgPreview src={previewImg} layout="auto"/>
            </div>
            
            <div>
                <h3> 게시물 내용</h3>
                <textarea ref={content}>{my_post[post_index].content}</textarea>
            </div>
            <button onClick={updatePost}>수정하기</button>
        </Container>
    )
}

⬆️ 수정페이지에서 input type="file"과 "radio"에 기존 정보 그대로 넣고 싶었던 나의 발악 (Edit.js)

  1. 일단 나는 작성 페이지와 수정 페이지 컴포넌트가 각자 존재한다 ... 동복님이 알고리즘으로 한 컴포넌트 안에 작성하셨다고 하니까 근시일 내에 바짓가랑이 붙잡으러 가야겠다.

  2. 그리고 수정 페이지에서 나는 기존 포스트의 이미지 파일이 이미 업로드 되어있고, 선택했던 라디오버튼이 이미 체크되어 있는 상황을 원했는데 실패했다. 레이아웃 미리보기에 기존 이미지 파일을 미리보게 하는건 성공했다. 은진님이 매커니즘 알려주셨다.



⬇️ 심화주차 개인과제 구현해야하는 기능 목록

기능 목록

  1. 게시글
    1. 목록 가져오기
    2. 추가하기 (+이미지 업로드하기)
    3. 삭제하기
    4. 수정하기
  1. 회원가입하기

  2. 로그인하기

  3. 파이어베이스 or S3로 배포!

페이지별 상세페이지별 상세

  1. 회원가입 페이지
    1. 이메일 형식 체크, 비밀번호 체크할 것
  2. 로그인 페이지
    1. 이메일, 패스워드 미기입 시 로그인 버튼 활성화 막을 것
  3. 메인 페이지(게시글 목록 페이지)
    1. 게시글 목록 노출
    2. 게시글 하나는 작성자, 작성 시간, 이미지 미리보기, 텍스트 내용으로 구성
    3. 게시글 하나를 클릭 시, 게시글 상세 페이지로 이동
  4. 글 작성 페이지
    1. 레이아웃 선택 버튼
      1. 3가지 레이아웃 중 선택하도록 한다.
        • 이미지가 오른편에, 텍스트는 왼편에 위치한 레이아웃
        • 이미지가 왼편에, 텍스트는 오른편에 위치한 레이아웃
        • 텍스트가 위에, 이미지는 아래에 위치한 레이아웃
      2. 레이아웃 선택 시, 게시글 레이아웃(모양새)대로 보이도록 한다.
      3. 텍스트, 이미지 중 입력 안된 게 있다면 게시글 작성 버튼 비활성화
      4. 작성 완료 시 메인 페이지로 이동
  5. 게시글 상세 페이지
    1. 게시글 레이아웃에 맞춰 이미지, 텍스트 위치 조절해서 노출


Axios

const userLogin = async () => {
        try {
          //데이터 안에서 원하는 정보 찾는 방법
            const reponse = await axios.get('http://localhost:5001/users',{
                params: {
                    "email":Email,
                    "password":Password
                }
            })
            console.log(...reponse.data);
            dispatch(addUser(...reponse.data));
            // setCurrentUser(reponse.data);
            history.push("/");

        } catch(error) {
            alert(error)
        }
    };

미니프로젝트 S.A. 피드백

React

협업을 하시기 전에 팀원 분들과 함께 코드 컨벤션을 맞춰보시는 것을 권장드려요!

코드 컨벤션
읽고, 관리하기 쉬운 코드를 작성하기 위한 일종의 코딩 스타일 규약이다.
신과 내가 아는 코드였는데 신만이 아는 코드가 되어버리는걸 방지하기 위해서 씀. (물론 동료들도 ...)

UX적으로 생각했을 때 꼭 로그인이 첫 페이지에 있어야 하는지 고민해보세요. 로그인이 꼭 필요한 경우가 아닌데 로그인을 요구하면 사용자 이탈율이 높아질 수 밖에 없답니다!

imageURL을 프론트에서 요청 바디에 보내는 것에 대해서 (1) 프론트에서 이미지 업로드를 써드파티(FB 같네요)를 이용해서 보내는게 좋을지 (2) FormData를 사용하여 이미지 자체를 보내고 백엔드에서 해당 리소스를 관리하는 것이 좋을지 논의를 해보시는게 좋을 것 같습니다.

Form Validation은 UX적으로 어떤 부분이 틀렸는지 명시해주는게 좋습니다. API 호출 전 프론트에서도 유효성 검증을 한 번 해보시는 것을 권장합니다. 또한 그 경우의 UX도 고려해보시고요.

현 스펙에서 메인 페이지에서 보여주는 List를 무한스크롤로 구현하는 부분은 없어 보여요. 시간이 되신다면 무한 스크롤, 페이지네이션, Windowing 기법을 적용해보시는 것도 좋을 것 같습니다.
📎 Windowing wars: React-virtualized vs. react-window

📎 리액트로 페이지네이션 구현하기

Windowing 기법
많은 데이터를 list 로 만들고 초기 렌더링에 모든 데이터를 불러오려면 굉장히 오랜 시간이 걸립니다. 사용자로서 긴 렌더링 시간이 불편하게 느껴질 수 있습니다.

이를 해결하기 위해서 list 중 viewport 에 보이는 부분만 렌더링하고 나머지는 스크롤 할 때 보이도록 하는 것을 권장합니다.
➡️ 이것을 Windowing 기법이라고 함.

github repo는 FE, BE를 분리하시는 것이 좋습니다.

작업을 본격적으로 하시기 전에 읽고 들어가 보세요! :) 필수는 아닙니다!!
📎 Thinking in React
리액트를 잘하기 위해서는 리액트적 사고를 잘 하는 것이 중요합니다. 여러분들께서 작업을 하시는 과정에서 리액트적 사고가 반영되고 있는지 체크해보세요!
📎 어떤 상황에서 하나의 컴포넌트를 여러 컴포넌트로 나누는 게 맞을까요?
처음부터 컴포넌트를 쪼개야 할 이유는 없습니다. (위 아티클과는 다소 상반된 의견이지만요 🤣) 그에 대한 이유를 설명합니다.
📎 어플리케이션 상태 관리 (Application State Management with React 한글 번역)
모든 상태를 GLOBAL로 두어야 할 이유는 없습니다. 그에 대한 이유를 설명합니다.

Thinking in React
Step 1: Break the UI into a component hierarchy
If your JSON is well-structured, you’ll often find that it naturally maps to the component structure of your UI. That’s because UI and data models often have the same information architecture—that is, the same shape. Separate your UI into components, where each component matches one piece of your data model. (데이터가 UI 어디에 들어갈지 먼저 생각하고 짜라는 거 같음 ...)

Step 2: Build a static version in React
This is called one-way data flow because the data flows down from the top-level component to the ones at the bottom of the tree. (데이터 방향 먼저 생각하라는 거같음 ...)
❗️ At this point, you should not be using any state values. That’s for the next step! (왜????)

Step 3: Find the minimal but complete representation of UI state
Think of state as the minimal set of changing data that your app needs to remember. The most important principle for structuring state is to keep it DRY (Don’t Repeat Yourself).

❗️ State로 이용하기 적절한 데이터 조건
Does it remain unchanged over time? If so, it isn’t state. (반대로 생각하고있었는데)
Is it passed in from a parent via props? If so, it isn’t state.
Can you compute it based on existing state or props in your component? If so, it definitely isn’t state!

Step 4: Identify where your state should live

Step 5: Add inverse data flow

4,5 뭔소린지 모르겠음 ....


어떤 상황에서 하나의 컴포넌트를 여러 컴포넌트로 나누는 게 맞을까요?
"만약 위에서 살펴본 문제를 직면하게 될 때, 컴포넌트를 여러 작은 컴포넌트로 나눠야 할 때입니다. 미리 나누지 말고요." 단일 컴포넌트를 여러 컴포넌트로 나누는 일을 우리는 "추상(abstraction)"이라고 부르고 있습니다. 추상은 멋지지만 모든 추상은 비용이 따릅니다. 그래서 추상에 되려 당하기 전에 이 비용과 이득에 대해 유의하고 있어야 합니다.

중복은 잘못된 추상보다 훨씬 저렴합니다. — Sandi Metz

:저는 미리 나눠요 데헷 ~


어플리케이션 상태 관리
확실히 하자면, 글로벌한 상태를 두는 것 자체는 정말이지 문제가 없다. 그러나 간단한 상태(예를 들면 모달이 열리는지 안열리는지를 결정하는 상태 또는 form의 input 값을 가지는 상태)를 글로벌하게 두는 것은 큰 문제다. 설상가상으로 이는 확장성에 별로 좋지 않다. 당신의 어플리케이션이 커질수록, 이 문제는 점점 더 커져버린다. 물론 여러분은 다른 reducer들을 연결해서 어플리케이션의 여러 다른 부분들을 관리할 수도 있지만, 모든 action creator와 reducer를 고려하면서 이런 간접적인 조치를 하는 것은 최적의 방법이 아니다.

: state props 사실 아직까지도 엄청 쓰기 까다롭다 ... 미니프로젝트하는 지금도 Axios 안에서 setState 후 props로 넘겨주기. 이걸 시도하고있어서 엄청 골치아픔 ... 그리고 부모자식이 되는 조건이 리턴 안에서 컴포넌트 자체를 호출하면서 넘겨주는 방식밖에 못봐서 진짜 ... 어떡해야하나싶고 걍 네캔만원 맥주 마시면서 코드짜고싶다 ...

profile
프론트엔드 개발자

0개의 댓글