useSelector with React.memo vs connect
useSelector with React.memo vs connect
参考自link。
https://react-redux.js.org/next/api/hooks#performance
据我所知,useSelector
钩子的好处是避免 wrapper hell。 Wrapper hell 由于使用 connect
HOC 正在发生。如果由于性能原因我们必须将 React.memo
HOC 与 useSelector
一起使用,那么简单地使用 connect
会更好吗? HOC 代替?因为在任何情况下,我们都必须处于 包装器的地狱 。如果 hell 不是 connect
那么就会是 React.memo
.
任何人都请解释 React.memo
相对于 connect
的好处。
好吧,首先,虽然 React.memo 是一个 HOC,但它并不创建与 connect 相同的嵌套。我创建了一个测试代码:
import React from "react";
import ReactDOM from "react-dom";
import {connect, Provider} from 'react-redux'
import { createStore } from 'redux'
import "./styles.css";
const MemoComponent = React.memo(function MyMemo() {
return <div>Memo</div>;
});
const ConnectedComponent = connect(null,null)(function MyConnected() {
return <div>ReduxConnectComponent</div>;
})
const store = createStore(()=>{},{})
function App() {
return (
<Provider store={store}>
<MemoComponent />
<ConnectedComponent/>
</Provider>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
这是呈现的结构:
我们可以看到 connect 的内容渲染得更深了。
其次,文档说:
by default useSelector() will do a reference equality comparison of the selected value when running the selector function after an action is dispatched, and will only cause the component to re-render if the selected value changed. However, unlike connect(), useSelector() does not prevent the component from re-rendering due to its parent re-rendering, even if the component's props did not change.
这意味着当商店的不相关部分发生变化时,useSelector 的组件将不会re-rendered。这是优化中最重要的部分。是否使用 React.memo 进行优化现在完全取决于您的决定,在大多数情况下,根本不需要它。我们仅在组件渲染成本非常高的情况下才使用 React.memo。
总而言之,需要连接包装器才能连接到商店。使用 useSelector 我们不必再换行了。在极少数情况下,当我们需要优化一些重量级组件时,我们仍然需要使用 React.memo 进行包装。 React.memo 的工作也是由 connect 完成的,但在大多数情况下,这是过早的优化。
我已经尝试了很长一段时间的答案,但我得到的答案并不明确。虽然 Redux 文档中的理论并不复杂:useSelector
使用严格相等 ===
而 connect 使用浅相等来确定。因此,在这两种情况下,如果您是 "pulling" 来自 Redux 状态(数字、字符串、布尔值)的原始值,您将获得相同的结果。如果值没有改变 none 的组件将重新呈现。如果你是 "pulling" 非基元(数组或对象)并且两种情况下的值都没有改变(useSelector,connect),那么使用 useSelector
的组件仍然会重新渲染 [] === []
将始终为 false,因为它们引用不同的数组,而 connect
ed 组件将不会重新呈现。现在为了使 useSelector
的行为相似而不是重新渲染,您可以这样做:
const object = useSelector(state => state.object, shallowEqual)
您可以从 react-redux
导入 shallowEqual
。或者通过使用 reselect
库来使用该状态的记忆版本:
const makeGetObject = () => createSelector(state => state.object, object => object)
并将其添加到您的选择器中,例如:const object = useSelector(state => state.object, makeGetObject);
我在试图找到它的底部时创建了这个代码框(检查 WithUseSelector
组件中的注释):useSelector vs connect()
我刚刚定制了 useSelector 钩子来避免这种情况,而且效果很好
import { useSelector, useDispatch } from 'react-redux'
import { _lodash } from '../../../lodash'
export const useCloneSelector = (selector = (obj) => obj) => {
const selectWithClonedState = (state = {}, ...others) => selector(_lodash.cloneDeep(state), ...others)
return useSelector(selectWithClonedState, _lodash.isEqual)
}
export { useDispatch, useSelector }
参考自link。 https://react-redux.js.org/next/api/hooks#performance
据我所知,useSelector
钩子的好处是避免 wrapper hell。 Wrapper hell 由于使用 connect
HOC 正在发生。如果由于性能原因我们必须将 React.memo
HOC 与 useSelector
一起使用,那么简单地使用 connect
会更好吗? HOC 代替?因为在任何情况下,我们都必须处于 包装器的地狱 。如果 hell 不是 connect
那么就会是 React.memo
.
任何人都请解释 React.memo
相对于 connect
的好处。
好吧,首先,虽然 React.memo 是一个 HOC,但它并不创建与 connect 相同的嵌套。我创建了一个测试代码:
import React from "react";
import ReactDOM from "react-dom";
import {connect, Provider} from 'react-redux'
import { createStore } from 'redux'
import "./styles.css";
const MemoComponent = React.memo(function MyMemo() {
return <div>Memo</div>;
});
const ConnectedComponent = connect(null,null)(function MyConnected() {
return <div>ReduxConnectComponent</div>;
})
const store = createStore(()=>{},{})
function App() {
return (
<Provider store={store}>
<MemoComponent />
<ConnectedComponent/>
</Provider>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
这是呈现的结构:
我们可以看到 connect 的内容渲染得更深了。
其次,文档说:
by default useSelector() will do a reference equality comparison of the selected value when running the selector function after an action is dispatched, and will only cause the component to re-render if the selected value changed. However, unlike connect(), useSelector() does not prevent the component from re-rendering due to its parent re-rendering, even if the component's props did not change.
这意味着当商店的不相关部分发生变化时,useSelector 的组件将不会re-rendered。这是优化中最重要的部分。是否使用 React.memo 进行优化现在完全取决于您的决定,在大多数情况下,根本不需要它。我们仅在组件渲染成本非常高的情况下才使用 React.memo。
总而言之,需要连接包装器才能连接到商店。使用 useSelector 我们不必再换行了。在极少数情况下,当我们需要优化一些重量级组件时,我们仍然需要使用 React.memo 进行包装。 React.memo 的工作也是由 connect 完成的,但在大多数情况下,这是过早的优化。
我已经尝试了很长一段时间的答案,但我得到的答案并不明确。虽然 Redux 文档中的理论并不复杂:useSelector
使用严格相等 ===
而 connect 使用浅相等来确定。因此,在这两种情况下,如果您是 "pulling" 来自 Redux 状态(数字、字符串、布尔值)的原始值,您将获得相同的结果。如果值没有改变 none 的组件将重新呈现。如果你是 "pulling" 非基元(数组或对象)并且两种情况下的值都没有改变(useSelector,connect),那么使用 useSelector
的组件仍然会重新渲染 [] === []
将始终为 false,因为它们引用不同的数组,而 connect
ed 组件将不会重新呈现。现在为了使 useSelector
的行为相似而不是重新渲染,您可以这样做:
const object = useSelector(state => state.object, shallowEqual)
您可以从 react-redux
导入 shallowEqual
。或者通过使用 reselect
库来使用该状态的记忆版本:
const makeGetObject = () => createSelector(state => state.object, object => object)
并将其添加到您的选择器中,例如:const object = useSelector(state => state.object, makeGetObject);
我在试图找到它的底部时创建了这个代码框(检查 WithUseSelector
组件中的注释):useSelector vs connect()
我刚刚定制了 useSelector 钩子来避免这种情况,而且效果很好
import { useSelector, useDispatch } from 'react-redux'
import { _lodash } from '../../../lodash'
export const useCloneSelector = (selector = (obj) => obj) => {
const selectWithClonedState = (state = {}, ...others) => selector(_lodash.cloneDeep(state), ...others)
return useSelector(selectWithClonedState, _lodash.isEqual)
}
export { useDispatch, useSelector }