본문 바로가기
WEB/기초

[WEB] React, Controlled Form, form 속성들, react hook multiple states.

by IT황구 2021. 7. 22.
728x90
반응형

강의도 슬슬 3주차입니다.

기초적인 것들은 앞에서 많이 다뤘고, 이제는 모두 다 포스팅하기에는 너무 길어서 제가 기억하고 싶은것만 쓰겠습니다.

강의를 듣고 복습하면서, 한번에 하지 못했던 것들입니다.

Controlled Form

-> React의 state와 Form의 input value를 일치시키는 것을 말합니다.

공식적 설명으로는, React에 의해서 Input form의 value가 제어되는 것을 말합니다.

onChange event를 이용해서 일치시킬 수 있습니다.

 

 

이렇게 생긴것을 만드는 과정에서 알게된 것 들을 적겠습니다.

Form을 만들기 위해 기본 react 엘리먼트인 input 이런것 대신에 'reactstrap'의 Form을 썼습니다.

reactstrap의

{ Form, FormGroup, Input, Label, Col, FormFeedback, Button } 을 사용했습니다.

<Form onSubmit={submitHandle} > 
  <FormGroup row> 
       <Label md={2} htmlFor="firstname">firstname</Label>
     <Col md={10}>
       <Input type="text" name="firstname" id="firstname" />
     </Col>
  </FormGroup>

위의 예제에서 기억하고 싶은것은 다음과 같습니다.

1. Form의 onSubmit을 통해서 <Button type="submit"> 에서의 call이 호출되게 됩니다

2. FormGroup에 row attribute를 통해서 하위 자식 컴포넌트들이 row로 배치되게 합니다.

3. md = {2}, md= {10}은 className="col-md-2" 이거 기억나시죠? 1 개의 row에는 최대 12개의 col만 가능합니다. 이건 지난번에 다뤘습니다. 따라서 label은 2/12 , Input은 10/12를 차지하게 합니다.

https://blog.naver.com/rbals0445/222427101246

 

[Web] React lifecycle method,props, super(props) vs super()

반갑습니다. 슬슬 길게쓰기 힘들어지네요.. 지난번에 만든 MyComponent를 약간 수정해보겠습니다. 원하는...

blog.naver.com

4. <Col>로 감싸주지 않으면 input은 아래로 내려가버립니다.

5. 새로운 Input하나를 아래 줄에 추가할때마다 <FormGroup>으로 감싸고 <Label> <Col><Input> 다시 반복해야합니다.

6. htmlFor 속성은 label을 클릭했을때 name이 같은 Input에 focus가 가게 해 줍니다. (직접 해보시면 이해가 빠릅니다)

Controlled Component를 하기 위해서는 Input의 onChange event를 이용해서 state와 같게 해주어야 하는데요.

이 과정에 앞서, react hook으로 여러개의 변수를 초기화 하는 방법에 대해서 알아보겠습니다.

 

const [val,setVal] = useState({ firstname : "", secondname : "", thirdname : "",});

const onChangeHandler = () => {
    setVal( (prev) => ({
       ...prev,
       firstname : "newname",
    }));
}

multiple value를 이용해서 hook을 사용하면 처음에 굉장히 당황스럽습니다. 안의 key,value들이 합쳐져서 올라가는게 아니고, firstname : "newname" 만 입력하면, secondname과 thirdname이 사라집니다.

useState Hook이 setState와 다른것은 setState는 이전의 pair을 merge하면서 가는건데, useState는 그냥 새로운 값으로 대체합니다. 즉 이전에 선언한 key,value들이 같이 사라져버립니다. 이걸 주의해야 합니다.

그러기 위해서는 setVal의 parameter와, spread operator를 이해해야 합니다.

우선 react의 hook에서 parameter는 자동으로 prev state를 지정해줍니다. 저건 그냥 hook의 속성이라고 생각하면 됩니다.

따라서 ...prev를 이용해서 기존의 state에서, firstname 부분만 바꾸게 해야 다른 값들이 유지가 되면서 state가 변경됩니다.

참고로 setVal ({ ...prev, firstname:"~~"})도 됩니다. -> 하지만 사용하면 안됩니다. 다른 케이스에서 문제가 있기 떄문입니다.

stale closure의 문제가 있는데, 이건 제가 지금 와닿지 않아서 나중에 포스팅 하도록 하겠습니다.

 

const handleInputChange = (event) => {
    let target = event.target;
    let value = target.type === "checkbox" ? target.touched : target.value;
    let name = target.name;
    setVal((prev) => ({ ...prev, [name]: value }));
    //console.log(value);
  };

<Input type="text" id="~~" name="~~" onChange={handleInputChange} />

onChange에는 parameter가 없는데 어떻게 event가 들어가나요?

그냥 이벤트핸들러라서, 모든 이벤트를 동일하게 처리하기 위해 자동으로 들어가는 것 입니다.

event.target.type을 하면 type도 알아낼 수 있고, value를 하면 그 안의 value도 알아 낼 수 있답니다.

https://ko.reactjs.org/docs/events.html

 

합성 이벤트(SyntheticEvent) – React

A JavaScript library for building user interfaces

ko.reactjs.org

그리고, [name]은 뭐냐고 하실 수 있습니다.

Computed property name으로 검색하시면 알 수 있습니다.

만약, 그냥 변수명 name을 갖다가 쓰면 js에서는 state의 object에서 name의 key값을 가지고 있는게 있나? 로 이해할 것입니다.

제가 필요한것은 firstname : "value" 입니다. 따라서 [name]을 사용하면 name을 계산하고 그것을 사용합니다.

[name] => firstname

따라서 firstname : value, 가 됩니다.

FormFeedback은 valid하지 않을때 그 아래부분에 빨갛게 나온 글씨를 말합니다. 이런식으로 valid가 아니면 FormFeedback이 나오게 할 수 있습니다.

<Input
                  type="text"
                  id="firstname"
                  name="firstname"
                  onChange={handleInputChange}
                  valid={touched["firstname"] && err.firstname.length === 0}
                  invalid={touched["firstname"] && err.firstname.length !== 0}
                  onBlur={handleBlur}
                  placeholder="First Name"
                />
                <FormFeedback>{err.firstname}</FormFeedback>

마지막으로,

이 부분을 표현하는 방법에 대해서 알아보곘습니다.

체크박스의 위치와 Input Component의 위치가 같으니 마음이 편합니다.

size와 offset에 대해서 알아보겠습니다.

size는 말그대로 크기, offset은 위치를 말합니다.

<Label md={2}>를 줬었죠? size가 2입니다.

따라서 그 다음부터는 바로 Input이 나옵니다.

offset을 2로 주면 (0,1, 2) 즉 3번의 위치부터 시작되므로 딱 맞출 수 있습니다.

size+offset = 8 이고, 아래도 size+offset = 4 이므로 col의 size가 총 12라서 1개의 row를 꽉 채우게 됩니다.

만약 여기서 size나 offset을 1만 더 올려주면 합이 13이 되기 때문에 row가 밀려나게 됩니다.

offset을 3으로 준 경우

 

<Col md={{ size: 6, offset: 2 }}>
                <FormGroup check>
                  <Input
                    type="checkbox"
                    id="agree"
                    name="agree"
                    onChange={handleInputChange}
                  ></Input>
                  <strong> May we contact you?</strong>
                </FormGroup>
              </Col>
              <Col md={{ size: 3, offset: 1 }}>
                <Input
                  type="select"
                  defaultValue="Tel."
                  onChange={handleInputChange}
                >
                  <option>Tel.</option>
                  <option>Email</option>
                </Input>
              </Col>

여기까지

Controlled Component 와 그걸 다루는 방법들에 대해서 알아봤습니다

감사합니다^^

728x90
반응형