[解決済み】コンポーネント内でuseStateからstate updaterを複数回呼び出すと、何度も再レンダリングされる。
質問
Reactフックを初めて試したのですが、データを取得して2つの異なる状態変数(データとロードフラグ)を更新すると、状態更新プログラムへの両方の呼び出しが同じ関数で起こっているにもかかわらず、私のコンポーネント(データテーブル)が2回レンダリングされることに気づくまでは、すべてが順調に思えたのです。以下は私のAPI関数で、両方の変数を私のコンポーネントに返しています。
const getData = url => {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(async () => {
const test = await api.get('/people')
if(test.ok){
setLoading(false);
setData(test.data.results);
}
}, []);
return { data, loading };
};
通常のクラスコンポーネントでは、複雑なオブジェクトになり得る状態を更新するために1つの呼び出しを行いますが、quot;hooks way"では状態をより小さなユニットに分割しているようです。これを軽減する方法について何かアイデアはありますか?
解決方法は?
を組み合わせることができます。
loading
ステートと
data
状態を1つの状態オブジェクトに統合し、1つの
setState
を呼び出すと、レンダリングは1回で済みます。
注意
とは異なり
setState
クラスコンポーネントでは
setState
から返される
useState
は、オブジェクトを既存の状態にマージするのではなく、オブジェクトを完全に置き換えるのです。もし、マージを行いたいのであれば、以前の状態を読み込んで、自分で新しい値とマージする必要があります。オブジェクトの
ドキュメント
.
パフォーマンスの問題があると判断するまでは、レンダーの過剰な呼び出しについてあまり心配する必要はないでしょう。Reactの文脈では)レンダリングと、仮想DOMの更新を実DOMにコミットすることは別の問題です。ここでいうレンダリングとは、仮想 DOM を生成することを指しており、ブラウザの DOM を更新することを指しているわけではありません。Reactでは、バッチ処理で
setState
の呼び出しを行い、最終的に新しい状態でブラウザ DOM を更新します。
const {useState, useEffect} = React;
function App() {
const [userRequest, setUserRequest] = useState({
loading: false,
user: null,
});
useEffect(() => {
// Note that this replaces the entire object and deletes user key!
setUserRequest({ loading: true });
fetch('https://randomuser.me/api/')
.then(results => results.json())
.then(data => {
setUserRequest({
loading: false,
user: data.results[0],
});
});
}, []);
const { loading, user } = userRequest;
return (
<div>
{loading && 'Loading...'}
{user && user.name.first}
</div>
);
}
ReactDOM.render(<App />, document.querySelector('#app'));
<script src="https://unpkg.com/[email protected]/umd/react.development.js"></script>
<script src="https://unpkg.com/[email protected]/umd/react-dom.development.js"></script>
<div id="app"></div>
代替案 - ステートマージャーフックを自作する
const {useState, useEffect} = React;
function useMergeState(initialState) {
const [state, setState] = useState(initialState);
const setMergedState = newState =>
setState(prevState => Object.assign({}, prevState, newState)
);
return [state, setMergedState];
}
function App() {
const [userRequest, setUserRequest] = useMergeState({
loading: false,
user: null,
});
useEffect(() => {
setUserRequest({ loading: true });
fetch('https://randomuser.me/api/')
.then(results => results.json())
.then(data => {
setUserRequest({
loading: false,
user: data.results[0],
});
});
}, []);
const { loading, user } = userRequest;
return (
<div>
{loading && 'Loading...'}
{user && user.name.first}
</div>
);
}
ReactDOM.render(<App />, document.querySelector('#app'));
<script src="https://unpkg.com/[email protected]/umd/react.development.js"></script>
<script src="https://unpkg.com/[email protected]/umd/react-dom.development.js"></script>
<div id="app"></div>
関連
-
Vueがechartsのtooltipにクリックイベントを追加するケーススタディ
-
vue3.0プロジェクトのアーキテクチャを構築するための便利なツール
-
jQueryのコピーオブジェクトの説明
-
Vueでルートネスティングを実装する例
-
Vueのフォームイベントのデータバインディングの説明
-
[解決済み】JavaScriptの配列でforEachが関数でない不具合
-
[解決済み】Node.jsで "Cannot find module "エラーを解決するには?
-
[解決済み】gulp anythingを実行するたびに、アサーションエラーが発生します。- タスク関数を指定する必要があります
-
[解決済み】ExpressJS - throw er Unhandled errorイベント
-
Uncaught TypeError: null のプロパティ 'offsetHeight' を読み取れませんでした。
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
JavaScriptにおけるマクロタスクとミクロタスクの詳細
-
jsを使った簡単な照明スイッチのコード
-
vueのグローバルがscss(mixin)を導入。
-
vueのプロジェクトでモックを使用する方法を知っていますか?
-
[解決済み】JavaScriptの配列でforEachが関数でない不具合
-
[解決済み】リソースの読み込みに失敗した:Bind関数でサーバーが500(Internal Server Error)のステータスで応答した【非公開
-
[解決済み】ReactJSでエラー発生 Uncaught TypeError: Super expression は null か関数でなければならず、undefined ではありません。
-
フロントエンド非同期(アシンク)ソリューション(全ソリューション)
-
JSクリックイベント - Uncaught TypeError: プロパティ 'onclick' に null を設定できません。
-
[解決済み] 変数が関数型かどうかのチェック