Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

React 세미나2 로그인 안된 상태에서는 접근금지 #237

Open
TheoLee72 opened this issue Oct 11, 2022 · 6 comments
Open

React 세미나2 로그인 안된 상태에서는 접근금지 #237

TheoLee72 opened this issue Oct 11, 2022 · 6 comments
Labels
html / css / js javascript 관련 내용 question 질문으로 사용될 이슈 React React 관련 내용
Milestone

Comments

@TheoLee72
Copy link
Collaborator


import './New.css';
import {useCounterContext} from "./CounterContext";
import Header from "./Header";
import {useNavigate} from "react-router-dom";
import React, {useState} from "react";

function New() {
    const {addMenu, menus, loginStatus} = useCounterContext();
    const [enteredNum, setEnterdNum] = useState("");
    const changeEnteredNum = (e) => {

        const value: string = e.target.value;
        const removedCharacterValue = value.replace(/[^0-9]/g, '');

        const removedCommaValue: number = Number(removedCharacterValue.replaceAll(",", ""));
        setEnterdNum(removedCommaValue.toLocaleString());
    };
    const navigate = useNavigate();
    const Goout = () => {
        navigate("/stores/1");
    };

    const addbutton = () => {
        const inputName = document.getElementById('name').value;
        const inputType = document.getElementById('typeselect').value;
        const inputImage = document.getElementById('image').value;
        const inputDes = document.getElementById('description').value;
        if (inputName === "" || enteredNum === ""|| inputType=== "") {
            alert("빼먹은 부분이 없느지 확인해주세요");
        } else {
            let isexist = menus.some((menu)=>menu.name===inputName);
            if (isexist === false) {
                if (inputName.length <= 20) {
                    if (Number(enteredNum.replaceAll(",", ""))>=100 && Number(enteredNum.replaceAll(",", ""))<=1000000) {
                        addMenu(inputName, enteredNum, inputImage, inputType, inputDes);
                        Goout();
                    }
                    else {
                        alert("가격이 범위에 맞지 않습니다. (100<price<1000000)");
                    }
                }
                else {
                    alert("이름이 너무 깁니다.");
                }
            }
            else {
                alert("동일한 이름의 제품이 이미 존재합니다.");
            }
        }
    };

    if (loginStatus === true)
    {
        return 1;
    }
    else
    {
        alert("GoOut");
        navigate(-1);
        return 0;

    }
    {/*return (
            <>
                <Header/>
                <section className="Newsection">
                    <div className="title">새 메뉴 추가</div>
                    <div className="nameadd-str">이름</div>
                    <input type="text" placeholder="맛있는와플" id="name" className="nameadd-box"/>
                    <div className="typeadd-str">종류</div>
                    <select id="typeselect" className="typeadd-box">
                        <option value='' selected>상품의 종류를 선택하세요</option>
                        <option value='coffee'>커피</option>
                        <option value='waffle'>와플</option>
                        <option value='beverage'>음료</option>
                    </select>
                    <div className="priceadd-str">가격</div>
                    <input type="text" value={enteredNum} onChange={changeEnteredNum} placeholder="5,000"
                           className="priceadd-box"/>
                    <span className="unit">원</span>
                    <div className="imageadd-str">상품 이미지</div>
                    <input type="text" placeholder="이미지 주소를 입력해주세요" id="image" className="imageadd-box"/>
                    <div className="desadd-str">설명</div>
                    <textarea placeholder="상품에 대한 자세한 설명을 입력해주세요" id="description" className="desadd-box"></textarea>

                </section>
                <button className="add" onClick={addbutton}>
                    추가
                </button>
                <button className="close" onClick={Goout}>
                    취소
                </button>
            </>

        );*/}


}

export default New;

menus/new에 loginstatus가 false면 접근하지 못하게 하려고 합니다.
일단 new 다 만들어두었고 그 기능만 추가하면 됩니다.
하지만 테스트하는 과정에서 alert는 두번 뜨고 navigate(-1)은 작동을 안하는 것을 확인했습니다.
어떻게 고쳐야하나요?

@TheoLee72 TheoLee72 added question 질문으로 사용될 이슈 React React 관련 내용 html / css / js javascript 관련 내용 labels Oct 11, 2022
@TheoLee72 TheoLee72 modified the milestone: seminar-1 Oct 11, 2022
@joongwon joongwon added this to the seminar-2 milestone Oct 11, 2022
@woohm402
Copy link
Member

질문과는 관련 없지만 github 에 코드를 올릴 땐 color syntax 를 이용할 수 있습니다!

적용 전적용 후
const MyComponent = () => {
  return <div>asdf</div>
}
const MyComponent = () => {
  return <div>asdf</div>
}

이거 적용하면 코드가 훨씬 더 보기 편해져요 :) 자세한 내용은 문서 참고해주세요!

@joongwon
Copy link
Contributor

보통 navigate(-1) 하면 잘 되어야할텐데 이상하네요... 코드를 실행해봐야 정확한 원인을 알 수 있겠지만 일단은 -1 대신에 다른 숫자(-2,-3 등)를 넣어보면서 직접 디버깅해보시는 게 좋겠습니다. 또 alert는 코드 실행을 멈추는 side effect(?)도 있기 때문에 디버깅은 console.log 사용하시기 바랍니다.

@fluentmin
Copy link
Collaborator

fluentmin commented Oct 11, 2022

안녕하세요! 비슷한 문제를 겪었는데 이게 정확한 해결방법이 아닌 미봉책 같지만 그래도 공유드립니다..!

  1. alert가 두 번 뜨는 문제 -> index.js에서 App 컴포넌트의 부모인 React.StrictMode를 없애(거나 주석처리해)주면 alert가 한 번만 뜨더라구요.
  2. navigate(-1)이 안 되는 문제 -> useNavigate 대신 Navigate를 사용해서 해당 함수 부분의 return 문에
return (
        <Navigate to={-1} />
    );

과 같이 써주면 이전 페이지로 이동되긴 하였습니다.

둘 다 왜 저런 문제가 발생하였는지는 모른 채로 우선 해결방법만 공유드리는데, 혹시 이유를 아신다면 추가로 코멘트 부탁드립니다!

@woohm402
Copy link
Member

woohm402 commented Oct 11, 2022

위 코멘트에 이어서 질문과 관련된 코멘트를 해보면, navigate 함수를 render 레벨에서 사용하고 계신 것 같습니다. react-router-dom 소스코드를 뜯어보면, 이 부분에 의해 render 중에 실행한 navigate 함수는 아무 역할도 하지 않고 215번 줄에 의해 return 됩니다. 아마 콘솔을 열어보시면 해당 소스코드 211번 줄에 나와 있는 아래 문구가 보일 것 같은데, 맞을까요?

You should call navigate() in a React.useEffect(), not when your component is first rendered.

해결을 위해서는 경고문구에도 나와 있듯 navigate 로직을 render 레벨에서 effect 훅 내부 (혹은 그에 준하는 곳) 로 옮겨야 할 것 같습니다. 사실 이 이슈 때문이 아니더라도, 리액트에서 render 레벨에서는 side effect 가 발생하지 않는 코드를 짜야 하기 때문에, render 레벨 대신 effect 훅 내부에 해당 로직이 있는 게 맞습니다.

즉, 가령 아래처럼 되어야 할 거예요.

기존변경
function New() {
  // ...

  if (loginStatus !== true) {
    alert("GoOut");
    navigate(-1);
    return 0;
  }

  // ...
}
function New() {
  // ...

  useEffect(() => {
    if (loginStatus !== true) {
      alert("GoOut");
      navigate(-1);
    }
  }, [loginStatus, navigate]);

  // ...

  if (!loginStatus) return 0;

  // ...
}

좀더 예쁘게 짜면 이런 식으로 될 것 같네요 👀 (설명을 위해 주석 떡칠했습니다)

function CreateWafflePage() { // 뭐하는 컴포넌트인지는 모르겠지만.. new 는 동사니까 컴포넌트 이름에 적합한 네이밍은 아니긴 합니다. 역할에 맞게 이름을 적절하게 변경하면 좋을 것 같아요
  // ...

  useEffect(() => {
    // 자바스크립트의 환장할 truthy falsy 때문에 호불호가 갈리긴 하지만, 간결함을 위해 (=== true) 는 생략하는 게 좀더 일반적입니다.
    // 이 변수 이름도, ~status 라는 suffix 가 붙어있다면 boolean 값보다는 enum 이나 string 인 게 나아 보입니다. boolean 변수의 네이밍은 is~ prefix 가 붙는 게 일반적입니다. ex) isLoggedIn
    if (loginStatus) return;

    // 원래 여기 alert 가 있었는데, alert 는 사용하지 않는 게 좋습니다. 사용자에게 피드백을 주고 싶다면 toast 등 다른 형태의 ui를 이용하는 게 낫습니다.
    navigate(-1); 
  }, [loginStatus, navigate]); // 굳이 매 렌더 이후마다 실행될 필요는 없는 로직이므로 dependency array 를 처리해 줍니다.
  // ...

  if (!loginStatus) return null; // 기존처럼 0 을 리턴하면 화면에 0 이 보여집니다. 화면에 아무것도 보여주지 않는 걸 의도하신 것 같은데, 이땐 null 을 리턴하면 됩니다. (null 대신 undefined, false 등등도 가능하지만, null이 제일 일반적입니다. 최근에 나온 react 18부턴 undefined 를 리턴할 수 있게 되어, 그냥 return; 으로 처리하는 것도 좋은 방법이 될 수 있습니다.)

  // ...
}

@woohm402
Copy link
Member

woohm402 commented Oct 11, 2022

@fluentmin

  1. alert가 두 번 뜨는 문제 -> index.js에서 App 컴포넌트의 부모인 React.StrictMode를 없애(거나 주석처리해)주면 alert가 한 번만 뜨더라구요.

저도 옛날에는 항상 귀찮아서 react.strictmode 를 항상 비활성화했었는데, 리액트 제대로 쓰려면 결국 strictmode 를 켜놓는게 많은 도움이 되더라구요! 그래서 웬만하면 켜두시는 걸 추천합니다 👍

https://ko.reactjs.org/docs/strict-mode.html

위 공식문서에도 나와 있듯 두번 호출되는 건 리액트에서 의도적으로 그렇게 처리한 거고, 개발 환경에서만 두 번씩 보여지며 프로덕션 빌드 시에는 한 번만 보여집니다!

image

@fluentmin
Copy link
Collaborator

@woohm402
남겨주신 코멘트와 링크들 살펴보며 몰랐던 부분들 많이 배웠습니다. 감사합니다!
리액트 공식문서와도 친해져야겠네요..ㅎㅎ

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
html / css / js javascript 관련 내용 question 질문으로 사용될 이슈 React React 관련 내용
Projects
None yet
Development

No branches or pull requests

4 participants