최근 오디오 재생 기능을 구현하면서 중복 재생이 되는 문제를 해결했다. 오디오를 재생하려고 함수를 실행할때마다 오디오 재생 함수에서 new Audio()
메소드를 실행하니 리렌더링 과정에서 계속 실행되면서 여러개의 Audio 객체가 만들어졌다.
중복 재생을 차단해야 돼서 고민하던 중 리렌더링을 막으려면 결국 상태로 관리해야 된다는 결론에 도달해서 ContextAPI + useReducer 조합을 사용하게 됐다.
컴포넌트 전체에서 사용하는 데이터를 제공한다.
상태 업데이트를 컴포넌트 외부에서 할 수 있다.
An alternative to useState.
useReducer is usually preferable to useState when you have complex state logic that involves multiple sub-values. It also lets you optimize performance for components that trigger deep updates because you can pass dispatch down instead of callbacks.
감을 다 잃어서 많이 해맸다. create-react-app 이후 HandsOn 느낌으로 만들어봤다. 가장 간단한 형태를 만들고 차근차근 집어가며 만드는게 큰 도움이 된다.
import {createContext} from 'react';
const CounterContext = createContext(null);
export default CounterContext;
const counterReducer = (state, action) => {
switch (action.type) {
case '@get':
return state;
case '@plus':
return state + 1;
case '@minus':
return state - 1;
default:
return state;
}
};
export default counterReducer;
import {useReducer} from 'react';
import Movie from './movie/Movie';
import CounterContext from './reducer/CounterContext';
import counterReducer from './reducer/counterReducer';
function App() {
const [counterState, counterDispatch] = useReducer(counterReducer, 0);
return (
<CounterContext.Provider value={{counterState, counterDispatch}}>
<div className="App">
<p>App.js</p>
<Movie />
</div>
</CounterContext.Provider>
);
}
export default App;
ConuterContext
컴포넌트를 입력한다. CounterContext
의 value
인자값에 할당된 데이터가 할당된다.import {useContext} from 'react';
import CounterContext from '../reducer/CounterContext';
const Movie = () => {
const counterReducer = useContext(CounterContext);
return (
<div>
<hr />
<p>Movie.jsx</p>
<p>counter state = {counterReducer.counterState}</p>
<button onClick={() => counterReducer.counterDispatch({type: '@plus'})}>+</button>
<button onClick={() => counterReducer.counterDispatch({type: '@minus'})}>-</button>
</div>
);
};
export default Movie;