useReducerでspread演算子を使用する必要がありますか?
編集:ブライアンの答えを確認した後、2番目の例でも、削除...state
すると1番目の例と同じ動作が発生することがわかったため、この質問をするのは間違っていました。何が原因で間違った動作が見られたのかわかりません。ご不便をおかけして申し訳ありません。ブライアンの答えは、使用法の良い説明です。
次の2つのコードスニペットを比較してください。initialState
一方が使用useState
し、もう一方が使用することを除いて、2つの状態を同時に更新することで同じことを行いますuseReducer
。
useState
const {useState} = React;
const initialState = {
name: 'John',
age: 20
};
const Example = () => {
const [state, setState] = useState(initialState);
const handleName = () => {
setState({...state, name: 'Tom'});
}
const handleAge = () => {
setState({...state, age: 30});
}
return (
<div>
<p>{state.name}</p>
<p>{state.age}</p>
<button onClick={handleName}>
Click to change name
</button>
<button onClick={handleAge}>
Click to change age
</button>
</div>
);
};
ReactDOM.render(
<Example />,
document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react"></div>
useReducer
const {useReducer} = React;
const initialState = {
name: 'Tom',
age: 30
}
const reducer = (state, action) => {
switch (action.type) {
case 'name':
return {
...state,
name: 'John'
}
case 'age':
return {
...state,
age: 25
}
default:
return state
}
}
const Example = () => {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<div>
<p>Name: {state.name}</p>
<p>Age: {state.age}</p>
<button onClick={() => dispatch({ type: 'name' })}>Click to update name</button>
<button onClick={() => dispatch({ type: 'age' })}>Click to update age</button>
</div>
)
};
ReactDOM.render(
<Example />,
document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react"></div>
...state
最初の例で削除すると、状態が単一のキーと値のペアに設定されるため、機能しなくなります。2番目の例でも同じことが起こると思っていましたが、そうではありませんでした。2番目の例は、スプレッド演算子を削除するとうまく機能します。
2番目の例について3つの質問があります。
- スプレッド演算子の用途は何ですか?
- スプレッド演算子を削除した後も機能するのはなぜですか?
- スプレッド演算子がなくてもうまく機能する場合、2番目の例ではスプレッド演算子は必要ないということですか?
回答
私は、これは非常によく似質問であることを理解し、この1、私はうまくいけば、誤った情報を得ることから、将来のリーダーを防ぐために、とにかく答えを与えています。
どちらuseState
もuseReducer
全く以前の値のいずれかのマージを行います。以前の状態値を保持することは、状態の更新中(setState
呼び出しまたはレデューサー関数定義のいずれか)の責任です。
これは、以下の変更されたコードではっきりとわかります。私が変更したのは...state
、各スイッチケースからを削除することだけです。
const {useReducer} = React;
const initialState = {
name: 'Tom',
age: 30
}
const reducer = (state, action) => {
switch (action.type) {
case 'name':
return {
name: 'John'
}
case 'age':
return {
age: 25
}
default:
return state
}
}
const Example = () => {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<div>
<p>Name: {state.name}</p>
<p>Age: {state.age}</p>
<button onClick={() => dispatch({ type: 'name' })}>Click to update name</button>
<button onClick={() => dispatch({ type: 'age' })}>Click to update age</button>
</div>
)
};
ReactDOM.render(
<Example />,
document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react"></div>
スプレッド演算子がこの目的で頻繁に使用される理由は、変更されていないすべての値を新しいオブジェクトに配置するための最も面倒な方法ではないためです。