+ 알아야 할것
useState 훅과 useEffect 훅
+ 실습
App.jsx class component를 function 컴포넌트로 바꾸고 hook 적용
Player.jsx class component를 function 컴포넌트로 바꾸고 hook 적용
App.jsx 훅 적용
먼저 class component를 function 컴포넌트로 바꾸고 차례대로 적용한다.
class 의 state 선언을 useState 훅으로 전환한다(L2)
componentDidMount 부분을 useEffect 훅으로 전환한다(L4 ~ L11) this.setState 는 setPlayers로 변경(L9).
useState, useEffect 이 두가지 훅은 class 컴포넌트에서 function 컴포넌트로 변경시 필수로 사용해야 하는 훅이다. 나머지 훅들은 주로 성능 개선의 이유로 주로 사용되지만 이 두가지 훅은 반드시 변경해야 한다.
클래스 컴포넌트에서 사용된 함수는 모두 함수 표현식으로 변경한다(L13, L24, L 49). 또한 함수 안에 사용된 this.setState는 모두 setPlayers 함수로 변경한다(L19, L33, L45)
render 함수는 단순히 리턴구문으로 변경한다(L56 ~ L70). this.state 가 사용된 부분은 모두 제거한다(L58). 그리고 함수 호출에서 사용된 this 도 모두 제거한다(L64, L65, L66, L68).
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | const App = (props) => {   const [players, setPlayers] = useState([]);   useEffect(() => {     axios.get('http://api.eastflag.co.kr:8000/api/score/list')       .then(response => {         console.log(response);         const {data} = response;         setPlayers(data);       });   }, [])   const handleRemovePlayer = (id) => {     axios.delete(`http://api.eastflag.co.kr:8000/api/score?id=${id}`)       .then(response => {         console.log(response);         const {data} = response;         if (data.result === 0) {           setPlayers(players.filter(item => item.id !== id));         }       });   }   const handleChangeScore = (id, delta) => {     console.log('id: ' + id, 'delta: ' + delta);     const copyPlayers = [ ...players ];     copyPlayers.forEach(player => {       if (player.id === id) {         player.score += delta;       }     })     setPlayers(copyPlayers);   }   const handleAddPlayer = (name) => {     console.log(name);     axios.post('http://api.eastflag.co.kr:8000/api/score', {name})       .then(response => {         console.log(response);         const {data} = response;         const copyPlayers = [ ... players ];         copyPlayers.unshift(data);         setPlayers(copyPlayers);       });   };   const getHighScore = () => {     const maxObject = _.maxBy(players, 'score');     const highScore = maxObject.score;     // 0은 디폴트이므로  0보다 클 경우만 highScore로 지정한다.     return highScore > 0 ? highScore : null;   }   return (     <div className="container p-3">       <Header title="My scoreboard" players={players} />       {/*Players List*/}       { players.map(item =>         <CustomPlayer key={item.id}                       name={item.name} score={item.score} id={item.id}                       isHighScore={item.score === getHighScore()}                       removePlayer={handleRemovePlayer}                       changeScore={handleChangeScore} />) }       <AddPlayerForm addPlayer={handleAddPlayer}></AddPlayerForm>     </div>   ) } | 
AddPlayerForm.jsx 훅으로 변경
생성자 함수안에 createREf()는 useRef()로 변경(L2, L3).
state 변수는 useState 훅으로 변경(L4)
함수는 함수 표현식으로 모두 변경(L6, L10). 함수 내부에 선언된 this는 모두 삭제한다(L7, L13 ~ L14, L24, L25)
render 함수안에 있는 return문만 가져온다(L30 ~ L49). 내부에 선언된 this는 모두 삭제한다(L32, L33, L36, L39)
		
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | export const AddPlayerForm = (props) => {   const formRef = useRef();   const textRef = useRef();   const [value, setValue] = useState('');   const handleValueChange = (e) => {     setValue(e.target.value);   };   const handleSubmit = (e) => {     e.preventDefault();     const form = formRef.current; // form node     const player = textRef.current; // input node     console.log(player.validity.valid);     console.log(form.checkValidity());     if (!form.checkValidity()) {       form.classList.add('was-validated');       return;     }     props.addPlayer(value);     setValue('')     form.classList.remove('was-validated');   }   return (     <div className="container">       <form ref={formRef} noValidate             className="row player align-items-center needs-validation" onSubmit={handleSubmit}>         <div className="col-9">           {/*<label htmlFor="playerName" className="form-label">Player Name</label>*/}           <input ref={textRef}                  type="text" className="form-control" id="playerName" placeholder="input player name"                  required                  value={value} onChange={handleValueChange}></input>           <div className="invalid-feedback">             Please input name.           </div>         </div>         <div className="col-3 d-grid">           <button type="submit" className="btn btn-primary">Add Player</button>         </div>       </form>     </div>   ) } | 
