이 글은 [[한글자막] React 완벽 가이드 with Redux, Next.js, TypeScript]를 수강하며 정리한 글입니다.

 

 

⚛️ 기본 환경: IDE: VS code, Language: React

 

 

useSelector(state => state.module)

: 저장소에 등록된 데이터(상태, State)를 가져와서 쓸 수 있는 Hook

 : Redux 스토어의 상태 객체를 매개변수로 받고, 그 상태에서 필요한 값을 선택적으로 반환
즉, Redux 상태 객체에서 counter 속성을 선택하여 반환

* useSelector 사용 시, react-redux는 해당 컴포넌트를 저장소에 자동으로 구독 설정

즉, 저장소 데이터가 변경될 경우에 자동으로 최신 카운터를 전달 받음

 

 

useDispatch()

: Redux 저장소에 action에 대한 type을 전달하여 상태 업데이트

 

 

사용 예시

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
import {useSelector, connect, useDispatch} from 'react-redux';
// useSelector: 저장소가 관리하는 데이터 access
// connect: class Component 사용할 경우 추가
// Class Component를 감싸는 Wrapper로 사용하여 Wrapper로 감싸진 Class Component를 저장소에 연결
 
import classes from './Counter.module.css';
 
const Counter = () => {
 
  const counter = useSelector(state => state.counter);
 
  const dispatch = useDispatch();
 
  const incrementHandler = () => {
    dispatch({type: 'increment'});
  };
  const decrementHandler = () => {
    dispatch({type: 'decrement'});
  };
 
  const toggleCounterHandler = () => {};
 
  return (
    <main className={classes.counter}>
      <h1>Redux Counter</h1>
      <div className={classes.value}>-- COUNTER VALUE: {counter} --</div>
      <div>
        <button onClick={incrementHandler}>Increment</button>
        <button onClick={decrementHandler}>Decrement</button>
      </div>
      <button onClick={toggleCounterHandler}>Toggle Counter</button>
    </main>
  );
};
 
export default Counter;
 
 
 

 

이 글은 [[한글자막] React 완벽 가이드 with Redux, Next.js, TypeScript]를 수강하며 정리한 글입니다.

 

 

🟨 기본 환경: IDE: VS code, Language: JavaScript

 

 

Redux 작동 방식

Redux: Application 내부의 하나의 중앙 데이터(=상태, state) 저장소

Component: Redux를 구독하여 데어터가 변경될 때마다 필요한 데이터를 전달 받음

Reducer Function: 저장소의 데이터 변경(≠useReducer)

 - Input: Old State, Dispatched Action

 - Output: New State Object

Action: 버튼 클릭 등 이벤트의 발생

 - Component에서 일어나며(=Trigger) Reducer가 수행할 작업을 설명하는 객체

 - Redux는 Action을 Reducer로 전달하고 Reducer가 작업을 수행

Mutate: action을 수행한 Reducer가 새로운 상태를 Redux로 전달

 

 

Redux 사용 방법

1. redux.js 파일 생성

 

2. redux.js파일이 있는 곳에서 npm 설치

[Terminal]

1
2
3
npm init -y
npm install redux
 
 

 

3. Redux import

1
2
const redux = require('redux');
 
 
 

 

4. 저장소 및 Reducer 함수 생성

1
2
3
4
5
6
7
8
9
10
const redux = require('redux');
 
const counterReducer = (state = {counter: 0}, action) => {
    return {
        counter: state.counter + 1
    };
};
 
const store = redux.createStore(counterReducer);
 
 
 

* Reducer의 실행은 Redux가 함으로 함수명만 작성

 

5. Redux를 구독할 함수 및 Action 생성

1
2
3
4
5
6
7
const counterSubscriber = () => {
    const latestState = store.getState();
    console.log(latestState);
};
 
store.subscribe(counterSubscriber); // 데이터 변경 시 실행
 
 
 

* Subscribe Func의 실행은 Redux가 함으로 함수명만 작성

 

6. 파일 저장 및 실행

[Terminal]

1
node redux.js
 

 

7. Action 생성 및 발송

1
2
store.dispatch({type: 'increment'}); // Action(식별자 역할을 하는 타입 prop을 가진 객체) 발송
 
 
 

Action(식별자 역할을 하는 타입 prop을 가진 객체) 발송 → Reducer 호출 → 새로운 state 반환

 

8. counterReducer에서 type에 따른 로직 변경

1
2
3
4
5
6
7
8
9
10
const counterReducer = (state = {counter: 0}, action) => {
    if(action.type === 'increment'){
        return {
            counter: state.counter + 1,
        };
    }
 
    return state;
};
 
 
 

 

9. 파일 저장 및 실행

[Terminal]

1
2
3
4
node redux.js
 
# {counter: 1}
 
 

 

이 글은 [[한글자막] React 완벽 가이드 with Redux, Next.js, TypeScript]를 수강하며 정리한 글입니다.

 

 

⚛️ 기본 환경: IDE: VS code, Language: React

 

 

React.createContext()

: 컴포넌트에게 props를 사용하지 않고 필요한 데이터를 넘겨주며 사용할 수 있게 해 줌으로써 컴포넌트들이 데이터(state)를 더 쉽게 공유할 수 있도록 함

 

React.createContext() 사용법

1. React createContext() 선언

1
2
3
4
5
6
7
8
9
import React from 'react';
 
const AuthContext = React.createContext({
    isLoggedIn: false
});
// AuthContext: Component는 아니지만 Component를 포함하는 객체
 
export default AuthContext;
 
 
 

 

2. AuthContext가 필요한 Component 감싸기

1
2
3
4
5
6
7
8
9
10
  return (
    <AuthContext.Provider value={{isLoggedIn: isLoggedIn,}}>
      <MainHeader isAuthenticated={isLoggedIn} onLogout={logoutHandler} />
      <main>
        {!isLoggedIn && <Login onLogin={loginHandler} />}
        {isLoggedIn && <Home onLogout={logoutHandler} />}
      </main>
    </AuthContext.Provider>
  );
 
 
 

⭐ AuthContext 자체는 component가 아니므로 Provider를 같이 사용하여 Component화

→ <AuthContect.Provider> 안의 Component들은 모두 AuthContext의 데이터를 공유

 * Provider 역할: 값 설정 및 전달

 

3. AuthContext 사용 선언

 - <AuthContext.Consumer>

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
const Navigation = (props) => {
  return (
     <AuthContext.Consumer>
       {(ctx) => {
         return (
          <nav className={classes.nav}>
            <ul>
              {ctx.isLoggedIn && (
                <li>
                  <a href="/">Users</a>
                </li>
              )}
              {ctx.isLoggedIn && (
                <li>
                  <a href="/">Admin</a>
                </li>
              )}
              {ctx.isLoggedIn && (
                <li>
                  <button onClick={props.onLogout}>Logout</button>
                </li>
              )}
            </ul>
          </nav>
         );
       }}
     </AuthContext.Consumer>
  );
};
 
 
 

 - useContext()

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
const Navigation = (props) => {
  const ctx = useContext(AuthContext);
 
  return (
    <nav className={classes.nav}>
      <ul>
        {ctx.isLoggedIn && (
          <li>
            <a href="/">Users</a>
          </li>
        )}
        {ctx.isLoggedIn && (
          <li>
            <a href="/">Admin</a>
          </li>
        )}
        {ctx.isLoggedIn && (
          <li>
            <button onClick={props.onLogout}>Logout</button>
          </li>
        )}
      </ul>
    </nav>
  );
};
 
 
 

 

 

 

참고 자료

 

초보자를 위한 리액트 Context - 완벽 가이드 (2021)

리액트 context는 모든 리액트 개발자들이 필수적으로 알아야 하는 개념입니다. context는 앱에서 state를 쉽게 공유할 수 있게 해줍니다. 이 글에서는 리액트 context가 무엇인지, 어떻게 사용하는지,

www.freecodecamp.org

 

이 글은 [[한글자막] React 완벽 가이드 with Redux, Next.js, TypeScript]를 수강하며 정리한 글입니다.

 

 

⚛️ 기본 환경: IDE: VS code, Language: React

 

 

React.useReducer()

: 현재 상태와 액션 객체를 파라미터로 받아와서 새로운 상태를 반환해주는 함수

: 컴포넌트의 상태 업데이트 로직을 컴포넌트에서 분리시킬 수 있음

 

useReducer() 의 사용법

1
2
const [state, dispatch] = useReducer(reducer, initialState);
 
 
 

 

 - state: 컴포넌트에서 사용 할 수 있는 상태

 - dispatch: 액션을 발생시키는 함수

▶ 예: dispatch({ type: 'INCREMENT' })

 - reducer: reducer 함수

 - initialState: 초기 상태

 

1. useReducer() 선언

1
2
3
4
5
  const [emailState, dispatchEmail] = useReducer(emailReducer, {
    value: '',
    isValid: null,
  });
 
 
 

 

2. emailReducer() 선언

1
2
3
4
5
  const [emailState, dispatchEmail] = useReducer(emailReducer, {
    value: '',
    isValid: null,
  });
 
 
 

 * state = emailState

 * action = dispatchEmail()이 전달한 객체

 

 

3. dispatchEmail 선언을 통한 emailReducer() 호출

1
2
    dispatchEmail({type: 'USER_INPUT', val: event.target.value});
 
 
 

 

4. 호출된 emailReducer()에 dispatchEmail()을 통해 전달받은 데이터를 통한 로직 구현

1
2
3
4
5
6
7
8
9
const emailReducer = (state, action) => {
 
  if(action.type === 'USER_INPUT'){
    return {value : action.val, isValid: action.val.includes('@')};
  }
 
  return {value: '', isValid: false};
};
 
 
 

 

5. useReducer() 사용

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
const Login = (props) => {
  const [emailState, dispatchEmail] = useReducer(emailReducer, {
    value: '',
    isValid: null,
  });
  const emailChangeHandler = (event=> {
    dispatchEmail({type: 'USER_INPUT', val: event.target.value});
    setFormIsValid(
      event.target.value.includes('@'&& enteredPassword.trim().length > 6
    );
  };
  const validateEmailHandler = () => {
    dispatchEmail({type: 'INPUT_BLUR'});
    
  };
  const submitHandler = (event=> {
    event.preventDefault();
    props.onLogin(emailState.value, enteredPassword);
  };
  return (
    <Card className={classes.login}>
      <form onSubmit={submitHandler}>
        <div
          className={`${classes.control} ${
            emailState.isValid === false ? classes.invalid : ''
          }`}
        >
          <label htmlFor="email">E-Mail</label>
          <input
            type="email"
            id="email"
            value={emailState.value}
            onChange={emailChangeHandler}
            onBlur={validateEmailHandler}
          />
        </div>
      </form>
    </Card>
  );
};
 
 
 

 

⭐ 컴포넌트에서 관리하는 값이 여러개가 되어서 상태의 구조가 복잡해진다면 useReducer로 관리하는 것이 편함

 

 

 

참고 자료

 

20. useReducer 를 사용하여 상태 업데이트 로직 분리하기 · GitBook

20. useReducer 를 사용하여 상태 업데이트 로직 분리하기 이 프로젝트에서 사용된 코드는 다음 링크에서 확인 할 수 있습니다. useReducer 이해하기 우리가 이전에 만든 사용자 리스트 기능에서의 주

react.vlpt.us

 

이 글은 [[한글자막] React 완벽 가이드 with Redux, Next.js, TypeScript]를 수강하며 정리한 글입니다.

 

 

⚛️ 기본 환경: IDE: VS code, Language: React

 

 

React.useEffect()

: 모든 컴포넌트가 렌더링된 이후 특정 작업을 실행시켜주는 Hook

: HTTP request, Browser 저장소에 저장 등 sideEffect를 처리

 

* useEffect(function, dependencies)

 - function: 수행하고자하는 작업

 - dependencies: 의존성 배열, 업데이트를 의존시키고 싶은 값 설정

 

 

1. useEffect(function)

: Rendering시마다 실행

 

2. useEffect(function, [])

: Component를 첫 rendering 시에만 실행

1
2
3
4
5
6
  useEffect(() => {
    setFormIsValid(
      enteredEmail.includes('@'&& enteredPassword.trim().length > 6
    );
  }, []);
 
 
 

❌ 올바른 입력값 형식에도 불구하고, 첫 rendering에만 useEffect()가 실행되므로 Login Btn이 활성화되지 않음

 

3. useEffect(function, [dependencies])

: dependencies에 선언된 변수값이 변할 때마다 rendering

1
2
3
4
5
6
  useEffect(() => {
    setFormIsValid(
      enteredEmail.includes('@'&& enteredPassword.trim().length > 6
    );
  }, [enteredEmail, enteredPassword]);
 
 
 

⭐ 단, 함수를 추가할 경우, function()으로 작성하면 결과값이 의존성에 추가되므로 function으로 작성하여 함수 자체를 의존성에 추가해야 함

 

4. setTimeout(() => {}, sec)

: 어떤 함수를 실행하기 전에 sec만큼 대기

1
2
3
4
5
6
7
8
9
10
  useEffect(() => {
    setTimeout(() => {
      console.log('Checking Form Validation');
      setFormIsValid(
        enteredEmail.includes('@'&& enteredPassword.trim().length > 6
      );  
    }, 500); // 0.5s씩 지연되어 setFormIsValid 실행
 
  }, [enteredEmail, enteredPassword]);
 
 
 

 

5. cleanUp function

: return () => {]

: 첫번째 useEffect()가 실행되고 난 이후, useEffect 함수가 다시 실행되기 전에 실행

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  useEffect(() => {
    const identifier = setTimeout(() => {
      console.log('Checking Form Validation');
      setFormIsValid(
        enteredEmail.includes('@'&& enteredPassword.trim().length > 6
      );  
    }, 500); // 0.5s씩 지연되어 setFormIsValid 실행
 
    return () => {
      console.log('CLEANUP');
      clearTimeout(identifier);
    };
 
  }, [enteredEmail, enteredPassword]);
 
 
 

cleanUp 함수를 통해서 setFomisVallid가 0.5초 뒤에 실행되지 전에 timer를 초기화시켜서 과도하게 formIsValid가 실행되는 것을 방지할 수 있음

[dependencies] 값을 유효성 검사를 충족시켰는지 여부에 따른 변수로 선언 시 useEffect() 호출을 줄일 수 있음

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  const {isValid: emailIsValid} = emailState;
  const {isValid: pwdIsValid} = pwdState;
  // 객체 destructuring (value, alias)
 
  useEffect(() => {
    const identifier = setTimeout(() => {
      console.log('Checking form validity!');
      setFormIsValid(
        emailIsValid && pwdIsValid
      );
    }, 500);
 
    return () => {
      console.log('CLEANUP');
      clearTimeout(identifier);
    };
  }, [emailIsValid, pwdIsValid]);
 
 
 

 

 

 

참고 자료

 

React Hooks : useEffect() 함수

useEffect 함수는 리액트 컴포넌트가 렌더링 될 때마다 특정 작업을 실행할 수 있도록 하는 Hook 이다. useEffect는 component가 mount 됐을 때, component가 unmount 됐을 때, component가 update 됐을 때, 특정 작업을

xiubindev.tistory.com