React Hooks

<aside> 💡 class없이 state를 사용할 수 있는 새로운 기능

</aside>

클래스형 컴포넌트 vs 함수형 컴포넌트 ( useEffect 사용)

import React, { Component } from 'react'
import Axios from 'axios'

export default class Hello extends Component {
    **constructor(props) {
        super(props);
        this.state = { name: " " };
    } //1번째: 생성자 실행으로, state가 초기화된다.**

    componentDidMount() {
        Axios.get('/api/user/name')
            .then(response => {
    this.setState({ name: response.data.name })
    }) // 서버에 요청을 보낸다. 실제 유저의 데이터를 가져온다음에 state에 넣어준다. state가 업데이트 되면 그때 컴포넌트가 다시 렌더링이 된다.
}

    **render() {
        return (
            <div>
                My name is {this.state.name}
            </div>
        )
    } // 2번째: 초기화 할때 { name: " " } 빈 스트링을 사용했으므로 My name is 빈 스트링이 되고, 그 후 response.data.name에서 받아온 이름을 가지고 실제 이름이 들어간다.**
}
import React, { useEffect, useState } from 'react'
import Axios from 'axios'

export default function Hello() {

    const [Name, setName] = useState("")
//useState를 이용해서 const [state, state를 이용하는 함수(관습적으로 set(state)를 사용한다.)] 로 구성한다.
useEffect(() => {
    Axios.get('/api/user/name') 
        .then(response => { 
            setName(response.data.name)
    })
}, []) //useEffect의 첫번쨰 매개변수로는 함수가, 두번째 매개변수로는 배열이 들어간다. 배열이 비어있으면, 컴포넌트가 마운트되고 함수를 한번만 호출한다. **그런데, 종속성배열 안에 [name]이 들어가 있으면, name이 바뀔 때마다 다시 호출된다.** 클래스형 컴포넌트에서는 componentDidUpdate문과 동일하다.

return (
    <div>
        My name is {Name}
    </div>
    )
}

다른 예시 - 일반 클래스 컴포넌트에서 생명주기 사용하는 부분을 hooks를 사용하여 변환

##일반 클래스 컴포넌트
**componentDidMount() {
    // 컴포넌트가 마운트 되면 updateLists 함수를 호출 
    this.updateLists (this.props.id)
}

componentDidUpdate (prevProps) {
    if (prevProps.id !== this.props.id) {
        //updatelists 함수를 호출할 때
        // 사용되는 id가 달라지면 다시 호출
        this.updateLists(this.props.id)
    }
}**
 
//updateLists 함수 정의
updateLists = (id) => {
    fetchLists(id)
        .then((lists) => this.setState({
            lists
        }))
}

**## React Hooks를 이용한 생명주기를 이용
useEffect(()=> {
    fetchLists(id)
        .then((repos)=>{
            setRepos(repos)
        })
}, [id])**

HOC

화면에서 재사용가능한 로직만을 컴포넌트로 만든다.

유저정보를 가져와서 state에 넣어주었다.

HOC 사용전

export default class Apage extends Component {
	state = {
		user: []
	}
	**componentDidMount() {
		fetchUsers()
			.then(users => {
				this.setState({ users })
			}) // A페이지와 B페이지 모두 해당: 유저정보를 어딘가에서 가져와서 State에 넣어줬다. => 모든 컴포넌트에서 같은 로직을 작성하면 매우 비효율적!!**
}

render() {
	const { users } = this.state;
	return (
		<div>
			A 페이지
			{users.map(({ name, url }) => (
				<div key={name}>
					<p>{name}, {url}</p>
				</div>
			))}
		</div>
	    )
    }
}
export default class Bpage extends Component {
    state = {
       user: []
    }

    **componentDidMount() {
        fetchUsers()
            .then(users => {
                this.setState({ users })
            })**
    }

    render() {  
        const { users } = this.state;
        return (
            <div>
                B 페이지
                {users.map(({ name, url }) => (
                    <div key={name}>
                        <p>{name}, {url}</p>
                    </div>
                ))}
            </div>
        )
    }
}

HOC 사용 후

Untitled

Untitled

return class usersHOC extends React.Component에서, HOC 클래스를 생성 후 userHOC 함수에서 return 해준다. componentDidMount() { … }에서 클래스 내에서 유저에 관한 작업(정보 받아오기)를 한 후 자녀 컴포넌트로 필요한 데이터를 내려준다.

오른쪽 사진에서, HOC 부모 컴포넌트에서 내려준 공통데이터를 사용할 수 있는데, Apage와 Bpage를 인자로 사용하여 왼쪽 state = { users: []} 에서 각각의 컴포넌트를 받아주고, component가 render 아래로 내려가므로, state를 props로 내려주면, 각각의 페이지에서 우측처럼 props로 유저정보를 가져온다. 실제로 중복되는 부분은 굉장히 많기 때문에 wrapper component가 매우 많아지는 단점이 있다. 해결방법은?

Custom Hooks 로 해결!

function **useAuth()** {
    const [users, setUsers] = useState([]); **//useAuth 라는 커스텀 훅스에서 유저 데이터를 다 가져온다.**

    useEffect(() => {   
        fetchUsers().then(users => {
            setUsers(users);
        });
    }, []);

    **return [users];**
}

function Apage() {

    **const [users] = useAuth();**
    
    return (
        <div>
            A 페이지
            {users.map(({ name, url }) => (
                <div key={name}>
                    <p>{name}, {url}</p>
                </div>
            ))}
        </div>
    );
}

리액트 Hooks를 이용해서 TicTacToe 앱을 함수형 컴포넌트로 바꾸기