私はおそらく非常に明白な何かを見逃しているので、自分自身をクリアしたいと思います。
これが私の理解です。
単純な反応コンポーネントには、states
とprops
があります。 state
でsetState
を更新すると、コンポーネント全体が再レンダリングされます。 props
はほとんど読み取り専用であり、更新しても意味がありません。
store.subscribe(render)
のようなものを介してreduxストアにサブスクライブする反応コンポーネントでは、ストアが更新されるたびに明らかに再レンダリングされます。
react-redux には、状態ツリーの一部(コンポーネントにとって重要なもの)とactionCreatorsをコンポーネントにprops
として注入するヘルパーconnect()
があり、通常は
const TodoListComponent = connect(
mapStateToProps,
mapDispatchToProps
)(TodoList)
しかし、setState
はTodoListComponent
がredux状態ツリーの変更(再レンダリング)に反応するために不可欠であるという理解では、state
またはsetState
を見つけることができません。 TodoList
コンポーネントファイルの関連コード。次のように表示されます。
const TodoList = ({ todos, onTodoClick }) => (
<ul>
{todos.map(todo =>
<Todo
key={todo.id}
{...todo}
onClick={() => onTodoClick(todo.id)}
/>
)}
</ul>
)
誰かが私が欠けているものについて正しい方向に私を指すことができますか?
追伸: redux package にバンドルされているtodoリストの例に従っています。
connect
関数は、ストアにサブスクライブするラッパーコンポーネントを生成します。アクションがディスパッチされると、ラッパーコンポーネントのコールバックが通知されます。次に、mapState
関数を実行し、shallow-compares今回の結果オブジェクトと前回の結果オブジェクトを比較します(つまり、同じ値でreduxストアフィールドをrewriteすると、再レンダリングはトリガーされません)。結果が異なる場合、結果を小道具として「実際の」コンポーネントに渡します。
Dan Abramovは( connect.js )でconnect
の非常に単純化されたバージョンを作成しました。 Redux performance に関するいくつかの記事へのリンクもあります。これらの記事では、関連するいくつかのアイデアについて説明しています。
update
React-Redux v6.0. 接続されたコンポーネントがストアからデータを受信する方法にいくつかの大きな内部変更を加えました。
その一環として、connect
APIとその内部構造がどのように機能し、それらがどのように変化してきたかを説明する投稿を書きました。
私の答えは、左のフィールドから少し外れています。この記事に私を導いた問題に光を当てます。私の場合、新しい小道具を受け取ったにもかかわらず、アプリは再レンダリングされていないようでした。
React開発者は、このよくある質問に対して、(ストア)が変更された場合、99%の時間でリアクションが再表示されない理由についての質問に答えました。しかし、他の1%については何もありません。突然変異はここではありませんでした。
TLDR;
componentWillReceiveProps
は、state
を新しいprops
と同期させる方法です。
エッジケース:state
が更新されると、thenアプリがdoes再レンダリングされます!
アプリがstate
のみを使用して要素を表示している場合、props
は更新できますが、state
は更新されないため、 -render。
Redux state
から受信したprops
に依存するstore
がありました。必要なデータはまだストアにないので、componentDidMount
から適切に取得しました。コンポーネントがmapStateToPropsを介して接続されているため、レデューサーがストアを更新したときに小道具を取り戻しました。しかし、ページはレンダリングされず、状態はまだ空の文字列でいっぱいでした。
これの例は、ユーザーが保存されたURLから「投稿の編集」ページをロードしたことです。 URLからpostId
にアクセスできますが、情報はまだstore
にないため、フェッチします。ページ上のアイテムは制御されたコンポーネントです。したがって、表示しているすべてのデータはstate
にあります。
Reduxを使用して、データがフェッチされ、ストアが更新され、コンポーネントはconnect
edになりましたが、アプリは変更を反映しませんでした。よく見ると、props
は受信されましたが、アプリは更新されませんでした。 state
は更新されませんでした。
さて、props
は更新および伝播されますが、state
は更新されません。 state
に更新を指示する必要があります。
render()
でこれを行うことはできず、componentDidMount
はすでにサイクルを終了しています。
componentWillReceiveProps
は、変更されたstate
値に依存するprop
プロパティを更新する場所です。
使用例:
componentWillReceiveProps(nextProps){
if (this.props.post.category !== nextProps.post.category){
this.setState({
title: nextProps.post.title,
body: nextProps.post.body,
category: nextProps.post.category,
})
}
}
この記事に、他の多数の投稿、ブログ、リポジトリが言及できなかった解決策を教えてくれた叫び声を上げなければなりません。この明らかに不明瞭な問題に対する答えを見つけるのに苦労した他の誰もが、ここにあります:
ReactJsコンポーネントのライフサイクルメソッド—詳細な説明
componentWillReceiveProps
は、state
更新と同期を保つためにprops
を更新する場所です。
state
が更新されると、thenフィールドはstate
doに応じて再レンダリングされます!
この回答は、Brian Vaughnの記事 おそらく派生国家は必要ない (2018年6月7日)の要約です。
小道具から状態を導出することは、あらゆる形態のアンチパターンです。古いcomponentWillReceiveProps
と新しいgetDerivedStateFromProps
の使用を含む。
小道具から状態を導出する代わりに、次の解決策を検討してください。
2つのベストプラクティスの推奨事項
function EmailInput(props) {
return <input onChange={props.onChange} value={props.email} />;
}
// parent class
class EmailInput extends Component {
state = { email: this.props.defaultEmail };
handleChange = event => {
this.setState({ email: event.target.value });
};
render() {
return <input onChange={this.handleChange} value={this.state.email} />;
}
}
// child instance
<EmailInput
defaultEmail={this.props.user.email}
key={this.props.user.id}
/>
何らかの理由で推奨事項があなたの状況に合わない場合、2つの選択肢があります。
class EmailInput extends Component {
state = {
email: this.props.defaultEmail,
prevPropsUserID: this.props.userID
};
static getDerivedStateFromProps(props, state) {
// Any time the current user changes,
// Reset any parts of state that are tied to that user.
// In this simple example, that's just the email.
if (props.userID !== state.prevPropsUserID) {
return {
prevPropsUserID: props.userID,
email: props.defaultEmail
};
}
return null;
}
// ...
}
class EmailInput extends Component {
state = {
email: this.props.defaultEmail
};
resetEmailForNewUser(newEmail) {
this.setState({ email: newEmail });
}
// ...
}
私はreduxだけが知っているように、ストアの状態が変化すると、コンポーネントが変更された状態に依存している場合にcomponentWillRecievePropsを呼び出し、コンポーネントを強制的に更新する必要があります
1-store state change-2-call(componentWillRecieveProps(()=> {3-component state change}))