Jam*_*uve 4 javascript closures reactjs react-native react-hooks
我正在尝试设置一个基本的自定义钩子来返回 React Native 中的设备方向。我旁边有一个功能代码示例,我不知道为什么这不起作用。我认为这是某种关闭/范围问题,但显然我不知道。
我知道有更简单的方法可以获取设备方向,但我想知道为什么这不起作用以及如何使其工作。
当前行为:调用setOrientation不会改变 的值orientation。预期行为:调用setOrientation更新 的值orientation。
一旦发生这种情况,我认为钩子会正常工作,因为null每次Dimensions更新时它都会返回。
[更新:为清晰起见编辑]
import { Dimensions, } from 'react-native';
function useDeviceDimensions() {
const [orientation, setOrientation] = useState(null);
useEffect(() => {
const setDimensions = (e) => {
console.log('running', orientation); // null
const {width, height} = e.window;
setOrientation(width > height ? 'landscape' : 'portrait');
};
Dimensions.addEventListener('change', setDimensions);
return () => Dimensions.removeEventListener('change', setDimensions);
}, [])
return orientation;
}
export default useDeviceDimensions;```
Run Code Online (Sandbox Code Playgroud)
setOrientation实际上改变的状态值orientation和useDeviceDimensions将返回改变orientation。问题在于您放置console.log语句的位置 - 您是对的,这与传递给useEffect.
useEffect仅使用您定义的回调调用一次。这个回调是一个闭包,可以orientation从useState. 在闭包创建时,orientation变量将具有值null。因为从来没有创建一个新的闭包([]在 中的依赖关系useEffect)null,当包含的更改侦听器被触发时,它总是会打印值。
但是,setOrientationinsidesetDimensions将调度并将更改传达给 React。流程是这样的:
useEffect闭合被调用一次在第一次呈现。change会触发一个事件。setDimensions在您的闭包内始终从函数外部作用域orientation变量(在构造时具有 value null)打印相同的值。setOrientation 被调用,React 在内部更新状态并在父组件中触发新的渲染周期。useDeviceDimensions从父组件再次调用,它现在具有并返回新orientation状态。第 4 点在闭包中起作用,因为 React 为每个组件都有一个“内存单元”的内部列表,它可以在其中读取和更新最近的状态,因此更新在闭包范围内工作(有关更多信息,请参见此处)。读取端orientation是一个陈旧的变量,如果你愿意,它只引用了 React 最初存储的第一个状态值。
useEffect以安全的方式声明您的useEffect钩子使用您在其依赖项数组中未提及的状态。React 文档对此有何评论:
如果您使用此优化,请确保数组包含组件范围内的所有值(例如 props 和 state),这些值随时间变化并被效果使用。否则,您的代码将引用先前渲染中的陈旧值。关联
因此,如果您还想使用orientationin useEffect,则可以将其声明为依赖项:
useEffect(() => {
...
}, [orientation]);
Run Code Online (Sandbox Code Playgroud)
看看这个Codesandbox的例子,希望它能澄清一点!
| 归档时间: |
|
| 查看次数: |
4845 次 |
| 最近记录: |