useState配列のReactフック内に要素をプッシュする方法は?それは反応状態の古い方法としてですか?または何か新しいもの?
useState配列のReactフック内に要素をプッシュする方法は?それは反応状態の古い方法としてですか?または何か新しいもの?
回答:
を使用useState
すると、状態アイテムの更新メソッドを取得できます。
const [theArray, setTheArray] = useState(initialArray);
次に、新しい要素を追加する場合は、その関数を使用して、新しい配列または新しい配列を作成する関数を渡します。通常は後者です。状態の更新は非同期であり、バッチ処理されることもあるためです。
setTheArray(oldArray => [...oldArray, newElement]);
次のような特定のユーザーイベントのハンドラーで配列を更新するだけの場合は、そのコールバックフォームを使用せずに逃げることができる場合がありますclick
(ただし、そうではありませんmousemove
)。
setTheArray([...theArray, newElement]);
Reactがレンダリングのフラッシュを保証するイベントは、ここにリストされている「離散イベント」です。
実例(コールバックをに渡すsetTheArray
):
theArray
そこへの唯一の更新はclick
イベント内のもの(「離散」イベントの1つ)であるため、次の場所で直接更新することで回避できますaddEntry
。
useEffect
例で何を言っているのかよくわかりません...?
useEffect
空の依存関係リストがある場合、[]
最初のレンダリング中にのみ実行されます。したがって、theArray
エフェクト内の値は常にになりますinitialArray
。setTheArray([...initialArray, newElement])
意味をなさない状況で、theArray
定数が常にに等しい場合はinitialValue
、機能の更新が必要です。
setTheArray(()=>theArray.concat(newElement))
はうまくいくと思ったが、NO!コールバックへのそのパラメータは、すべての違いになります。
もう少し拡張するために、ここにいくつかの一般的な例があります。で始まります:
const [theArray, setTheArray] = useState(initialArray);
const [theObject, setTheObject] = useState(initialObject);
配列の最後に要素をプッシュ
setTheArray(prevArray => [...prevArray, newValue])
オブジェクトの最後にある要素をプッシュ/更新します
setTheObject(prevState => ({ ...prevState, currentOrNewKey: newValue}));
オブジェクトの配列の最後にある要素をプッシュ/更新します
setTheArray(prevState => [...prevState, {currentOrNewKey: newValue}]);
配列のオブジェクトの最後にある要素をプッシュします
let specificArrayInObject = theObject.array.slice();
specificArrayInObject.push(newValue);
const newObj = { ...theObject, [event.target.name]: specificArrayInObject };
theObject(newObj);
ここにいくつかの実用的な例もあります。 https://codesandbox.io/s/reacthooks-push-r991u
Reactクラスコンポーネントの「通常の」状態で行うのと同じ方法です。
例:
function App() {
const [state, setState] = useState([]);
return (
<div>
<p>You clicked {state.join(" and ")}</p>
//destructuring
<button onClick={() => setState([...state, "again"])}>Click me</button>
//old way
<button onClick={() => setState(state.concat("again"))}>Click me</button>
</div>
);
}
// Save search term state to React Hooks with spread operator and wrapper function
// Using .concat(), no wrapper function (not recommended)
setSearches(searches.concat(query))
// Using .concat(), wrapper function (recommended)
setSearches(searches => searches.concat(query))
// Spread operator, no wrapper function (not recommended)
setSearches([...searches, query])
// Spread operator, wrapper function (recommended)
setSearches(searches => [...searches, query])
https://medium.com/javascript-in-plain-english/how-to-add-to-an-array-in-react-state-3d08ddb2e1dc
setTheArray([...theArray, newElement]);
が最も簡単な答えですが、theArray内の項目の変更に注意してください。配列アイテムのディープクローニングを使用します。
最も推奨される方法は、ラッパー関数とスプレッド演算子を一緒に使用することです。たとえば、name
このように呼ばれる状態を初期化した場合、
const [names, setNames] = useState([])
このようにこの配列にプッシュできます、
setNames(names => [...names, newName])
お役に立てば幸いです。
カスタム状態の最後にデータの配列を追加できます。
const [vehicleData, setVehicleData] = React.useState<any[]>([]);
setVehicleData(old => [...old, ...newArrayData]);
たとえば、以下にaxiosの例を示します。
useEffect(() => {
const fetchData = async () => {
const result = await axios(
{
url: `http://localhost:4000/api/vehicle?page=${page + 1}&pageSize=10`,
method: 'get',
}
);
setVehicleData(old => [...old, ...result.data.data]);
};
fetchData();
}, [page]);
useStateのオブジェクトの配列にオブジェクトをプッシュするために上記のメソッドを試しましたが、TypeScriptを使用すると次のエラーが発生しました。
タイプ 'TxBacklog [] | undefined 'には、iterator.ts(2488)を返す' Symbol.iterator 'メソッドが必要です。
tsconfig.jsonの設定は明らかに正しかった:
{
"compilerOptions": {
"target": "es6",
"lib": [
"dom",
"dom.iterable",
"esnext",
"es6",
],
この回避策は問題を解決しました(私のサンプルコード):
インターフェース:
interface TxBacklog {
status: string,
txHash: string,
}
状態変数:
const [txBacklog, setTxBacklog] = React.useState<TxBacklog[]>();
新しいオブジェクトを配列にプッシュします。
// Define new object to be added
const newTx = {
txHash: '0x368eb7269eb88ba86..',
status: 'pending'
};
// Push new object into array
(txBacklog)
? setTxBacklog(prevState => [ ...prevState!, newTx ])
: setTxBacklog([newTx]);
特定のインデックスの後にプッシュしたい場合は、以下のように実行できます。
const handleAddAfterIndex = index => {
setTheArray(oldItems => {
const copyItems = [...oldItems];
const finalItems = [];
for (let i = 0; i < copyItems.length; i += 1) {
if (i === index) {
finalItems.push(copyItems[i]);
finalItems.push(newItem);
} else {
finalItems.push(copyItems[i]);
}
}
return finalItems;
});
};
setTheArray(currentArray => [...currentArray, newElement])
上記がうまくいかない場合は試してみてください。ほとんどの場合ではuseEffect(...theArray..., [])
、それはそれは理解することが重要ですtheArray
ので、定数、ある機能の更新が未来からの値のために必要とされるレンダリング