- popup
- 컴포넌트 값 전달
- 함수, useState 줄이기
1) popup
js에서 bg를 이용해 popup을 만들었던 것과 비슷한 원리로 React popup을 구현해 보았다.
js에선 style display 속성값을 none / block 했다면, React에선 상태변수에 따라 popup내용이 있는 js를 호출하는 방식으로 했다.
// Test5
import React, { useState } from 'react';
import Test5Popup from './Test5Popup';
const Test5 = () => {
const [isOpen, setIsOpen] = useState(false)
const onPopup=()=>{
setIsOpen(true)
}
const offPopup=()=>{
setIsOpen(false)
}
return (
<div>
<button onClick={onPopup}>POPUP</button>
{
isOpen && <Test5Popup offPopup={offPopup}/>
}
</div>
);
};
export default Test5;
// Test5Popup
import React from 'react';
const Test5Popup = ({offPopup}) => {
return (
<>
<div className="bg" onClick={offPopup}></div>
<div className="popup">
<p className="closex">
<i className="xi-close-circle-o" onClick={offPopup}></i>
</p>
<h2>POPUP</h2>
</div>
</>
);
};
export default Test5Popup;
2) 컴포넌트 값 전달
나누어 놓은 컴포넌트에 서로 값을 주고받으려면 공통 부모의 컴포넌트에서 데이터를 처리해야 한다.
위와 같이 이름을 입력받는 컴포넌트와 동물 이름을 받는 컴포넌트, 둘을 합쳐서 출력해 주는 컴포넌트가 있을 때 세 컴포넌트의 데이터를 처리해 줄 부모 컴포넌트가 필요하다.
// Test7
import React, { useState } from 'react';
import Test7Name from './Test7Name';
import Test7Ani from './Test7Ani';
import Test7Display from './Test7Display';
const Test7 = () => {
const [text, setText] = useState('name')
const [ani, setAni] = useState('animal')
const changeInput1 = e=>{
const {value} =e.target
setText(value)
}
const changeInput2 = e=>{
const {value} =e.target
setAni(value)
}
return (
<div style={{margin:30}}>
<Test7Name text={text} changeInput1={changeInput1}/>
<hr/>
<Test7Ani ani={ani} changeInput2={changeInput2}/>
<hr/>
<Test7Display text={text} ani={ani}/>
</div>
);
};
export default Test7;
Test7 컴포넌트는 name, ani, display 컴포넌트의 공통 부모로서 데이터를 주고받는 역할을 한다.
// Test7Name
import React from 'react';
const Test7Name = ({text,changeInput1}) => {
return (
<div>
<h3>Test7Name</h3>
<label>Name : </label>
<input type="text" placeholder='이름 입력' onChange={changeInput1}/>
<span style={{marginLeft:30}}>{text}</span>
</div>
);
};
export default Test7Name;
// Test7Ani
import React from 'react';
const Test7Ani = ({ani, changeInput2}) => {
return (
<div>
<h3>Test7Ani</h3>
<label>Animal : </label>
<input type="text" placeholder='동물 입력' onChange={changeInput2}/>
<span style={{ marginLeft: 30 }}>{ani}</span>
</div>
);
};
export default Test7Ani;
// Test7Display
import React from 'react';
const Test7Display = ({text, ani}) => {
return (
<div>
<h3>{ani}의 이름은 {text}</h3>
</div>
);
};
export default Test7Display;
다른 컴포넌트 간 값을 주고받고, 함수를 전달해 주는 원리는 React 첫날에 배운 props 방식과 같다.
3) 함수, useState 줄이기
import React, { useRef, useState } from 'react';
const Test8 = () => {
const [id, setId] = useState('')
const [pw, setPw] = useState('')
const [email, setEmail] = useState('')
const idRef = useRef()
const changeInput1 = e => {
const { value } = e.target
setId(value)
}
const changeInput2 = e => {
const { value } = e.target
setPw(value)
}
const changeInput3 = e => {
const { value } = e.target
setEmail(value)
}
const onReset = () => {
setId('')
setPw('')
setEmail('')
idRef.current.focus()
}
return (
<div style={{ margin: 30 }}>
<p>
<input type="text" value={id} onChange={changeInput1} ref={idRef}/>
<input type="text" value={pw} onChange={changeInput2} />
<input type="text" value={email} onChange={changeInput3} />
<button onClick={onReset}>RESET</button>
</p>
<h4>ID : {id}</h4>
<h4>PW : {pw}</h4>
<h4>E-mail : {email}</h4>
</div>
);
};
export default Test8;
위와 같이 값을 받는 input이 3개 있을 때 각각 다른 onChange 함수를 넣어주고 id, pw, email에 대한 usestate를 총 3가지 만들어서 처리할 수 있지만, 아래 코드처럼 usestate를 하나로 만들어 구현할 수 있다.
import React, { useRef, useState } from 'react';
const Test8step2 = () => {
const [form, setForm] = useState({ id: '', pw: '', email: '' })
const idRef = useRef()
const { id, pw, email } = form
const changeInput1 = e => {
const { value } = e.target
setForm({
...form,
id: value
})
}
const changeInput2 = e => {
const { value } = e.target
setForm({
...form,
pw: value
})
}
const changeInput3 = e => {
const { value } = e.target
setForm({
...form,
email: value
})
}
const onReset = () => {
idRef.current.focus()
setForm({
id: "",
pw: "",
email: ""
})
}
return (
<div style={{ margin: 30 }}>
<p>
<input type="text" value={id} onChange={changeInput1} ref={idRef} />
<input type="text" value={pw} onChange={changeInput2} />
<input type="text" value={email} onChange={changeInput3} />
<button onClick={onReset}>RESET</button>
</p>
<h4>ID : {id}</h4>
<h4>PW : {pw}</h4>
<h4>E-mail : {email}</h4>
</div>
);
};
export default Test8step2;
form을 비구조 할당으로 id, pw, email을 받아 usestate를 하나로 줄였다.
여기서 onChange에 대한 실행문인 함수도 줄일 수 있다.
import React, { useRef, useState } from 'react';
const Test8step3 = () => {
const [form, setForm] = useState({ id: '', pw: '', email: '' })
const idRef = useRef()
const { id, pw, email } = form
const changeInput = e => {
const { value, name } = e.target
setForm({
...form,
[name]: value
})
}
const onReset = () => {
idRef.current.focus()
setForm({
['id']: "",
['pw']: "",
['email']: ""
})
}
return (
<div style={{ margin: 30 }}>
<p>
<input type="text" value={id} onChange={changeInput} ref={idRef} name="id" />
<input type="text" value={pw} onChange={changeInput} name="pw" />
<input type="text" value={email} onChange={changeInput} name="email" />
<button onClick={onReset}>RESET</button>
</p>
<h4>ID : {id}</h4>
<h4>PW : {pw}</h4>
<h4>E-mail : {email}</h4>
</div>
);
};
export default Test8step3;
각각 다른 input에 name 속성을 추가해 주었다.
change 된 input(e.target)의 value와 name을 가져온다.
그 값을 setForm에 넣게 되면 기존에 존재한 form(...form)을 남긴 채 뒤에 새로운 값을 추가해 준다.