
良い一日、友達!
useState()フックは、React機能コンポーネントの状態を管理します。クラスコンポーネントでは、状態はthis.stateに格納され、this.setState()メソッドが呼び出されて更新されます。
通常、州での作業は難しいことではありません。ただし、更新に関連する重要なニュアンスが1つあります。
状態はどのように更新されますか:即時(同期)または延期(非同期)?答えを見つけるために読んでください。
1. useState()で状態を更新します
そのような機能コンポーネントがあるとしましょう:
import { useState } from 'react'
function DoubleIncreaser() {
const [count, setCount] = useState(0)
const doubleIncreaseHandler = () => {
setCount(count + 1)
setCount(count + 1)
}
return (
<>
<button onClick={doubleIncreaseHandler}>
Double Increase
</button>
<div>Count: {count}</div>
</>
)
}
const [count、setCount] = useState(0)は、コンポーネントの初期状態を定義します。 countは現在の状態を含む変数であり、setCountはこの状態を更新する関数です。
コンポーネントには、倍増ボタンが含まれています。このボタンがクリックされると、doubleIncreaseHandlerハンドラーが呼び出され、カウントするために2つの連続した更新が実行されます。setCount(カウント+1)とsetCount(カウント+1)です。
ボタン1または2をクリックした後のコンポーネントの状態はどうなりますか?
この デモを開き、ボタンをクリックします。カウント値は、クリックするたびに1ずつ増加します。
setCount(count + 1)が状態を更新しても、カウント値はすぐには変更されません。代わりに、Reactは状態が更新されるようにスケジュールし、次にレンダリングされるときに、const [count、setCount] = useState(0)で、フックはカウントに新しい値を割り当てます。
例:変数countの値が0の場合、setCount(count + 1);を呼び出します。 setCount(count + 1)はsetCount(0 + 1)に評価されます。 setCount(0 + 1)-次のレンダリングの状態値として1になります。
したがって、[value、setValue] = useState()でsetValue(newValue)を使用して状態を更新することは、非同期で行われます。
ただし、状態更新関数は、現在の状態に基づいて新しい状態を計算するための引数としてコールバックを受け取ることができます。この場合、setCount(actualCount => actualCount + 1)を使用できます。
import { useState } from 'react'
function DoubleIncreaser() {
const [count, setCount] = useState(0)
const doubleIncreaseHandler = () => {
setCount(actualCount => actualCount + 1)
setCount(actualCount => actualCount + 1)
}
return (
<>
<button onClick={doubleIncreaseHandler}>
Double Increase
</button>
<div>Count: {count}</div>
</>
)
}
この関数を使用して状態を更新する場合、actualCount引数には実際の状態値が含まれます。
この デモを開き、ボタンをクリックします。予想通り、カウントは2に増えます。
もちろん、いつでも中間変数を作成できます。
import { useState } from 'react'
function DoubleIncreaser() {
const [count, setCount] = useState(0)
const doubleIncrease = () => {
let actualCount = count
actualCount = actualCount + 1
actualCount = actualCount + 1
setCount(actualCount)
}
return (
<>
<button onClick={this.doubleIncrease}>
Double Increase
</button>
<div>Count: {count}</div>
</>
)
}
actualCount = countは、必要に応じて更新できる中間変数です。この変数は、setCount(actualCount)を使用して状態を更新するために使用されます。
2.状態は不変(不変)で読み取り専用です
次のレンダリングで状態が更新されることを忘れた場合は、値を変更した直後に値の読み取りを試みることができます。残念ながら、何も得られません。
function FetchUsers() {
const [users, setUsers] = useState([])
useEffect(() => {
const startFetching = async () => {
const response = await fetch('/users')
const fetchedUsers = await response.json()
setUsers(fetchedUsers)
console.log(users) // => []
console.log(fetchedUsers) // => ['John', 'Jane', 'Alice', 'Bob']
}
startFetching()
}, [])
return (
<ul>
{users.map(user => <li>{user}</li>)}
</ul>
)
}
FetchUsersコンポーネントは、マウント要求を送信します-startFetching()。
データを受信すると、setUsers(fetchedUsers)が状態を更新します。ただし、変更は一夜にして行われません。
users変数は不変で、読み取り専用です。useState()フックのみが新しい値を割り当てることができます。これを直接行うことはできません。
function FetchUsers() {
const [users, setUsers] = useState([])
useEffect(() => {
const startFetching = async () => {
const response = await fetch('/users')
const fetchedUsers = await response.json()
users = fetchedUsers // ! users
users.push(...fetchedUsers) // ! users
setUsers(fetchedUsers) // !
}
startFetching()
}, [])
return (
<ul>
{users.map(user => <li>{user}</li>)}
</ul>
)
}
3.クラスコンポーネントの状態を更新します
非同期状態の更新は、クラスコンポーネントで一般的です。
例を考えてみましょう:
import { Component } from 'react';
class DoubleIncreaser extends Component {
state = {
count: 0
};
render() {
return (
<>
<button onClick={this.doubleIncrease}>
Double Increase
</button>
<div>Count: {this.state.count}</div>
</>
);
}
doubleIncrease = () => {
// !
this.setState(({ count }) => ({
count: count + 1
}));
this.setState(({ count }) => ({
count: count + 1
}));
// !
// this.setState({ count: this.state.count + 1 });
// this.setState({ count: this.state.count + 1 });
}
}
doubleIncrease()ハンドラーに注意してください。コールバック関数を使用して状態を更新します。
この デモを開き、ボタンをクリックします。this.stateの値は2に増加します。
クラスコンポーネントでは、this.stateもすぐには更新されません。this.setState(newState)が呼び出されると、Reactは次のレンダリングまでthis.stateの更新を延期します。
したがって、this.setState(newState)はthis.stateを非同期的に更新します。
4.結論
useState()フックとthis.setState()(クラスコンポーネント内)は、変数値とコンポーネントの状態を非同期に更新します。
単純なルールを覚えておいてください。useState()(またはthis.setState())フックのsetState(newValue)セッターを呼び出すと、状態はすぐには更新されませんが、コンポーネントの次のレンダリング時に更新されます。
Reactを(index.jsに)一度だけインポートする必要があることに気づきましたか?これは、コンポーネントでは不要になりました。
ご清聴ありがとうございました。良い一日を。