[react] 계산된 속성명(feat. 함수형 업데이트)

jini.choi·2023년 7월 17일
0

react

목록 보기
2/3

계산된 속성명 - 속성명을 미리 계산을 해서 그거에 맞는 데이터를 넣는다

❗️ 보기 전 알아야될 점!
모든태그에는 name 속성이 존재하지 않는다.
무작정 계산된 속성명 써서 name부여한다음 name 가져와서 뭘 해야겠다라는 생각XX

input태그가 아닌 곳에서 계산된 속성명을 쓸 경우 on~ 이벤트를 걸어준 다음 event console를 찍어보고 event.target 안에 있는 속성들을 보고 난 다음 거기에 내가 사용할 수 있는 속성들이 있는지 판단하고 해당 속성을 사용해야한다.(div태그는 name이 없음)

계산된 속성명을 사용하지 않을 때 문제점

계산된 속성명을 사용하지 않으면 비슷한 구조의 함수와 state를 input태그별로 생성해야된다.
(동일한 동작을 하고 있는데 state에 넣어주는 값만 다름)

const [inputId, setInputId] = useState("");
const [inputPw, setInputPw] = useState("");

const handleInputId = e => {
    setInputId(e.target.value);
  };

const handleInputPw = e => {
    setInputPw(e.target.value);
  };

계산된 속성명을 사용 한다면...?

1. state를 전부 포괄하는 useInput로 관리

2. useState는 객체로 관리 ({})

3. 객체 키는 기존에 만들었던 state 키로 생성

4. handleInput 함수 선언 - 각각에 input에서 이벤트가 이러나면 setUseInput에 안에 있는 내용을 변경 시켜줄때 사용

  const [useInput, setUseInput] = useState({
    id: '',
    pw: '',
  });

  const handleInput = e => {
    setUseInput();
  };

5. 현재는 하나의 함수 두개의 input이기 때문에 사용자는 어떤 input에 값을 넣고 있는지 알지만 컴퓨터입장에선 어디에 값이 들어오는지 모른다. 그것을 알게해주기 위해 속성값을 넣어줘야 한다.

실제 적용 전 console.log로 확인해보자!

6. console.log(e)를 찍어보면 이벤트 객체가 나오는데 우린 여기서 event.target.value를 가져오는 것이다.

  const handleInput = e => {
    console.log(e)
  };

targetinput이라고 되어있다. 왜냐면 event.target 은 이벤트가 일어나는 곳을 의미하기 때문

7. 현재 이벤트타겟이 어디서 일어나는지만 알고 어떤 데이터를 넣어야되는지는 모르는 상태임
-> 우선 console.log보면 input이 갖고 있는 속성들을 볼 수가 있는데 여기서 name을 이용해서 input태그가 어떤 이름을 갖고있게 부여를 해줘야함.

8. name의 값은 state의 키값으로 설정

    	<input 
      		className="userInput"
      		type="text"
			name="id"
      		placeholder="ID"
      		onChange={handleInput}
      	/>
		<input 
      		className="userInput"
      		type="password"
			name="pw"
      		placeholder="Password"
      		onChange={handleInput}
      	/>

설정 후 id input에 값을 넣으면 어떤 name을 갖고있는 input에서 이벤트가 일어났는지 handleInput함수에서 알 수 있다.
(console에 name이 설정된 것을 확인 할 수 있다.)

아래 콘솔 찍으면 위에 이미지에 있는 name 값 가져와서 찍힘 ->id 이런식으로

  const handleInput = e => {
    console.log(e.target.name);
  };

9. 이제 state에 자리에 맞게 넣어주기만 하면 된다.

  • state에 들어오는 값이 객체니까 key:value 형태로 넣어줌
  • event.target이 객체 타입이기 때문에 구조 분해할당으로 name과 value로 가져온다.const { name, value } = e.target;
  • setUseInput에 구조분해할당으로 가져온 namevalue를 준다.
  const [useInput, setUseInput] = useState({
    id: '',
    pw: '',
  });

  const handleInput = e => {
    const { name, value } = e.target;
    setUseInput({ name:value });
  };

❗️ 이렇게까지만 가져오면 나는 pw에 값을 넣는데 계속 id에만 값이 들어가게된다.
(사진에서는 email에 넣었는데 계속 name에 들어가는 상황)

🔆 특정값을 특정 키에 넣어주려면 { ...useInput,[name]:value } 이렇게 써줘야함

  • useInput state를 가져와서 ...useInput로 복제해준 다음 그곳에[name]:value로 업데이트하여 맞는 값을 넣어주겠다는 뜻
  const [useInput, setUseInput] = useState({
    id: '',
    pw: '',
  });

  const handleInput = e => {
    const { name, value } = e.target;
    setUseInput({ ...useInput,[name]:value });
  };

만약, { ...useInput, name:value } 이렇게 쓰게 될 경우 name이 선언은 됐지만 해당 값이 읽히지 않는다는 워닝이 뜸
왜냐하면 객체에 변수인 key를 name로 넣으면 string이라고 인식하여 name(string)이라고 고정으로 들어가 버린다.

그래서 변수라는 것을 알려주기 위해 [name]으로 작성해야 함

❌ 잘못된 예시
아래처럼 입력하고 id input에 값을 1이라고 입력하면 e.target.name에는 name 값인 id를 가져오고 e.target.value는 value값인 1이 들어오면서 useInput을 바꿔줄것인데 아래와 같이 사용하면 안된다.

  const [useInput, setUseInput] = useState({
    id: '',
    pw: '',
  });

  const handleInput = e => {
    setUseInput({e.target.name : e.target.value});
  };

최종

  const [inputValues, setInputValues] = useState({
    id: '',
    pw: '',
  });

  const handleInput = e => {
    const { name, value } = e.target;
    setInputValues({ ...inputValues, [name]: value });
  };

const Login = () => {
	return (
    	<input 
      		className="userInput"
      		type="text"
			name="id"
      		placeholder="ID"
      		onChange={handleInput}
      	/>
		<input 
      		className="userInput"
      		type="password"
			name="pw"
      		placeholder="Password"
      		onChange={handleInput}
      	/>
    )
}

함수형 업데이트를 사용하게된다면?

  • prev라는것은 setUseInput(setState)가 갖고있는 특징 중 하나(다른이름을 써도되지만 컨벤션임)
  • (prev)에 파마미터값을 넘겨주지 않더라도 (prev)로 인자를 넣게되면 이전값을 가져오는 특징을 가지고 있다.
  • useInput를 무조건 사용하지 않아도됨
  const [useInput, setUseInput] = useState({
    id: '',
    pw: '',
  });

  const handleInput = e => {
    const { name, value } = e.target;
    setUseInput((prev)=>({ ...prev,[name]:value }));
  };

함수형 업데이트의 또 다른 예시

모달창 구현 시

const [isModelOpen, setIsModelOpen] = useState(false);

1. 기존 사용방법
const handelModal = () => {
	setIsModelOpen(!isModelOpen)
}

2. 함수형 업데이트 사용방법
const handelModal = () => {
	setIsModelOpen((prev) => !prev)
}
profile
개발짜🏃‍♀️

1개의 댓글

comment-user-thumbnail
2023년 7월 17일

저도 개발자인데 같이 교류 많이 해봐요 ㅎㅎ! 서로 화이팅합시다!

답글 달기