import React, { useState } from 'react';
const InputSample = () => {
const [input, setInput] = useState({
name: '',
nickname:''
});
const {name, nickname} = input;
const onChange = (e) => {
const {value, name} = e.target;
setInput({
...input,
[name]: value
})
};
return (
<>
<input name="name" placeholder="이름" onChange={onChange} value={name} />
<input name="nickname" placeholder="닉네임" onChange={onChange} value={nickname}/>
</>
)
}
{users.map(user => (
<User user={user} key={user.id} />
))}
const [user, setUser] = useState([
{
id: 1,
username: 'shmallow',
email: 'shmallow@naver.com'
},
{
id: 2,
username: 'hypering',
email: 'glesmallow@naver.com'
}
]);
const nextId = useRef(4);
// 추가
const onCreate = () => {
const newUser = {
id: nextId.current,
username,
email
};
setUser(user.concat(newUser));
nextId.current += 1;
}
// 삭제
const onRemove = (id) => {
setUser(user.filter(user => user.id !== id));
}
// 수정
const onToggle = (id) => {
setUser(user.map(user => user.id === id ? {...user, active: !user.active}));
}
useEffect(() => {
console.log('컴포넌트가 화면에 나타남');
return () => {
console.log('컴포넌트가 화면에서 사라짐');
};
}, []);
// 리렌더링 -> onCreate가 새로 만들어지는데, props가 바뀌지 않으면
// 리렌더링 하지 않고 재사용할 수 있다.
const onCreate = useCallback(() => {
const newUser = {
id: nextId.current,
username,
email
}
setUser(user.concat(newUser));
nextId.current += 1;
}, [user, username, email]);
함수 안에서 사용하는 상태 혹은 props가 있다면, deps 배열안에 포함시켜야 한다.
만약에 deps 배열 안에 함수에서 사용하는 값을 넣지 않게 된다면, 함수 내에서 해당 값들을 참조할때 가장 최신 값을 참조 할 것이라고 보장 할 수 없다.
const countActiveUsers = (users) => {
console.log('활성 사용자 수를 세는중...');
return users.filter(user => user.active).length;
}
const count = useMemo(() => countActiveUsers(user), [user])
const CreateUser = ({ username, email, onChange, onCreate }) => {
return (
<div>
<input
name="username"
placeholder="계정명"
onChange={onChange}
value={username}
/>
<input
name="email"
placeholder="이메일"
onChange={onChange}
value={email}
/>
<button onClick={onCreate}>등록</button>
</div>
);
};
export default React.memo(CreateUser);
import React, { useState } from 'react';
function Counter() {
const [number, setNumber] = useState(0);
const onIncrease = () => {
setNumber(prevNumber => prevNumber + 1);
};
const onDecrease = () => {
setNumber(prevNumber => prevNumber - 1);
};
return (
<div>
<h1>{number}</h1>
<button onClick={onIncrease}>+1</button>
<button onClick={onDecrease}>-1</button>
</div>
);
}
export default Counter;
import React, { useReducer } from 'react';
const reducer = (state, action) => {
switch (action.type) {
case 'INCREMENT':
return state + 1;
case 'DECREMENT':
return state - 1;
default:
return state;
}
}
function Counter() {
const [number, dispatch] = useReducer(reducer, 0);
const onIncrease = () => {
dispatch({ type: 'INCREMENT' });
};
const onDecrease = () => {
dispatch({ type: 'DECREMENT' });
};
return (
<div>
<h1>{number}</h1>
<button onClick={onIncrease}>+1</button>
<button onClick={onDecrease}>-1</button>
</div>
);
}
export default Counter;
const UserDispatch = React.createContext(null);
const reducer = (state, action) => {
switch (action.type) {
case 'CREATE_USER':
return {
users: state.users.concat(action.user)
};
case 'TOGGLE_USER':
return {
...state,
users: state.users.map(user =>
user.id === action.id ? { ...user, active: !user.active } : user
)
};
case 'REMOVE_USER':
return {
...state,
users: state.users.filter(user => user.id !== action.id)
};
default:
return state;
}
}
export const UserDispatchContext = React.createContext(null);
export const UserStateContext = React.createContext(null);
const [state, dispatch] = useReducer(reducer, initialState);
<UserDispatchContext.Provider value={dispatch}>
<UserStateContext.Provider value={state}>
{children}
</UserStateContext>
</UserDispatchContext>
import { UserDispatchContext, UserStateContext } from './App';
const object = {
a: 1,
b: 2
};
const nextObject = {
...object,
b: 3
};