我目前正在创建一个 React Native 应用程序,但仍然不确定如何最好地处理我的用例的状态。
我使用react-native-svg
在应用程序中创建一个相当复杂的图形,该图形存储在组件中,保持不变并在父组件中检索。然后,此父组件在画布上定期旋转和平移,但复杂图形的路径不会更改。因此,由于计算相当繁重,我想仅在应用程序开始时计算该图的 SVG 路径,而不是在旋转或平移父组件时计算。目前,我的代码结构如下所示:
图形组件
const Figure = (props) => {
const [path, setPath] = useState({FUNCTION TO CALCULATE THE SVG PATH});
return(
<G>
<Path d={path} />
</G>
)
}
父组件
const Parent = (props) => {
return (
<View>
<Svg>
<G transform={ROTATE AND TRANSFORM BASED ON INTERACTION}>
<Figure />
</G>
</Svg>
</View>
)
}
如您所见,我正在为路径数据使用状态。我现在的问题:
- 我在这里是否确保此路径仅在启动时计算一次?
- 有没有更优雅/更好的方法来做到这一点(例如,我现在根本没有使用setter功能,所以我觉得这不是最佳实践)
编辑:
计算路径的函数取决于我从父组件传递的一些道具。
将值传递给useState
该值用于初始化状态。它不会在每次组件重新渲染时都设置,因此在您的情况下,只有在组件挂载时才会设置path
。
即使道具变了,path
状态也不会变。
由于您的初始状态取决于 prop,您需要做的就是从 props 中拉出相关 prop 并将其传递给计算初始path
值的函数:
const Figure = (props) => {
// get relevant prop
const { importantProp } = props;
// path will never change, even when props change
const [path] = useState(calculatePath(importantProp));
return(
<G>
<Path d={path} />
</G>
)
}
但是,即使未重新初始化path
值,每次渲染仍会计算calculatePath
函数。如果calculatePath
操作成本很高,请考虑改用useMemo
:
您可以通过将该 prop 添加到依赖项数组来确保仅当特定 prop 更改时才更新path
:
const Figure = (props) => {
const { importantProp } = props;
const path = useMemo(() => calculatePath(importantProp), [importantProp]);
return(
<G>
<Path d={path} />
</G>
)
}
在这种情况下,您根本不需要状态。
将importantProp
添加到useMemo
依赖项数组意味着每次importantProp
更改时,React 都会重新计算您的path
变量。
使用useMemo
将防止在每次渲染时评估昂贵的计算。
我创建了一个 CodeSandbox 示例,您可以在控制台中看到,只有在指定的道具important
发生变化时,才会重新计算路径。如果更改任何其他道具,则不会重新计算path
。
一个更优雅的选择是使用useState
的回调形式。如果向它传递一个函数,则只有在需要计算初始状态时(即在初始渲染时)才会调用该函数:
const [path, setPath] = React.useState(heavyCalculation);
const heavyCalculation = () => {
console.log('doing heavy calculation');
return 0;
};
const App = () => {
const [path, setPath] = React.useState(heavyCalculation);
React.useEffect(() => {
setInterval(() => {
setPath(path => path + 1);
}, 1000);
}, []);
return 'Path is: ' + path;
};
ReactDOM.render(<App />, document.querySelector('.react'));
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div class="react"></div>
正如您在上面的代码片段中看到的,doing heavy calculation
只记录一次。
您可以使用钩子useMemo,它将值返回给您的const,它接收返回值的函数和一个数组,发送一个空的计算一次,如果需要,您可以发送一些依赖项,props或状态,以便在它们更改时重新计算值。
在您的情况下,您可以执行以下操作:
const Figure = (props) => {
const path = React.useMemo(() => {
// calculate and return value for path
}, []);
return(
<G>
<Path d={path} />
</G>
)
}
它是为那只海豚而创造的。
希望对;)有所帮助!