以下のフックの例を考慮する
import { useState } from 'react';
function Example() {
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
基本的にthis.forceUpdate()メソッドを使用して、以下の例のようにReactクラスコンポーネントでコンポーネントをすぐに再レンダリングします。
class Test extends Component{
constructor(props){
super(props);
this.state = {
count:0,
count2: 100
}
this.setCount = this.setCount.bind(this);//how can I do this with hooks in functional component
}
setCount(){
let count = this.state.count;
count = count+1;
let count2 = this.state.count2;
count2 = count2+1;
this.setState({count});
this.forceUpdate();
//before below setState the component will re-render immediately when this.forceUpdate() is called
this.setState({count2: count
}
render(){
return (<div>
<span>Count: {this.state.count}></span>.
<button onClick={this.setCount}></button>
</div>
}
}
しかし、私のクエリは、上記の機能コンポーネントをフックですぐに再レンダリングさせるにはどうすればよいですか?
useState
は内部でuseReducer
を使用するため、これはuseState
またはuseReducer
で可能です。
const [, updateState] = React.useState();
const forceUpdate = useCallback(() => updateState({}), []);
forceUpdate
は、通常の状況下での使用を意図したものではなく、テストまたはその他の未解決のケースでのみ使用されます。この状況は、より一般的な方法で対処できます。
setCount
は、不適切に使用されたforceUpdate
の例です。 setState
はパフォーマンス上の理由で非同期であり、状態の更新が正しく実行されなかったからといって強制的に同期されるべきではありません。状態が以前に設定された状態に依存している場合、これは pdater function で行う必要があります。
前の状態に基づいて状態を設定する必要がある場合は、以下のupdater引数についてお読みください。
<...>
アップデーター関数によって受信された状態と小道具の両方が最新であることが保証されます。アップデータの出力は、状態と浅くマージされます。
setCount
は、目的が明確ではないため、実例ではないかもしれませんが、これはアップデーター関数の場合です:
setCount(){
this.setState(({count}) => ({ count: count + 1 }));
this.setState(({count2}) => ({ count2: count + 1 }));
this.setState(({count}) => ({ count2: count + 1 }));
}
コンポーネントは状態とプロップのみに依存し、期待どおりに機能することが望ましいですが、コンポーネントを強制的に再レンダリングする関数が本当に必要な場合は、useState
フックを使用して関数を呼び出すことができます必要です。
例
const { useState, useEffect } = React;
function Foo() {
const [, forceUpdate] = useState();
useEffect(() => {
setTimeout(forceUpdate, 2000);
}, []);
return <div>{Date.now()}</div>;
}
ReactDOM.render(<Foo />, document.getElementById("root"));
<script src="https://unpkg.com/[email protected]/umd/react.production.min.js"></script>
<script src="https://unpkg.com/[email protected]/umd/react-dom.production.min.js"></script>
<div id="root"></div>
他の人が述べたように、useState
は動作します-ここに mobx-react-lite が実装されています-あなたは同様のことができます。
新しいフックuseForceUpdate
を定義します-
import { useState, useCallback } from 'react'
export function useForceUpdate() {
const [, setTick] = useState(0);
const update = useCallback(() => {
setTick(tick => tick + 1);
}, [])
return update;
}
コンポーネントで使用します-
const forceUpdate = useForceUpdate();
if (...) {
forceUpdate(); // force re-render
}
https://github.com/mobxjs/mobx-react-lite/blob/master/src/utils.ts および https://github.com/mobxjs/mobx-を参照react-lite/blob/master/src/useObserver.ts
次のようにuseStateを簡単に定義できます。
const [, forceUpdate] = React.useState(0);
そして使用法:forceUpdate(n => !n)
この助けを願っています!
JSXコードでReactはブール値を出力しないという事実を利用して、通常のフックを(ab)使用して強制的に再レンダリングできます。
// create a hook
const [forceRerender, setForceRerender] = React.useState(true);
// ...put this line where you want to force a rerender
setForceRerender(!forceRerender);
// ...make sure that {forceRerender} is "visible" in your js code
// ({forceRerender} will not actually be visible since booleans are
// not printed, but updating its value will nonetheless force a
// rerender)
return (
<div>{forceRerender}</div>
)
潜在的なオプションは、key
を使用して特定のコンポーネントでのみ更新を強制することです。キーを更新すると、コンポーネントのレンダリングがトリガーされます(以前は更新に失敗しました)
例えば:
const [tableKey, setTableKey] = useState(1);
...
useEffect(() => {
...
setTableKey(tableKey + 1);
}, [tableData]);
...
<DataTable
key={tableKey}
data={tableData}/>