下面是两个几乎做同一件事的React组件。一个是功能;另一个是功能。另一个是一类。每个组件都有一个Animated.Value
和一个异步侦听器,该侦听器会在更改时更新_foo
。我需要能够像使用经典组件中的_foo
一样访问功能组件中的this._foo
。
FunctionalBar
,则_foo
在全局范围内不应包含FunctionalBar
。 FunctionalBar
不能在函数范围内包含_foo
,因为_foo
每次渲染时都会重新初始化FunctionalBar
。 _foo
也不应该处于状态,因为当_foo
更改时,该组件不需要呈现。ClassBar
不存在此问题,因为它在组件的整个生命周期内都在_foo
上this
进行了初始化。 如何在_foo
的整个生命周期中保持FunctionalBar
的初始化状态,而不将其置于全局范围内?
import React from 'react';
import { Animated, View } from 'react-native';
var _foo = 0;
function FunctionalBar(props) {
const foo = new Animated.Value(0);
_onChangeFoo({ value }) {
_foo = value;
}
function showFoo() {
let anim = Animated.timing(foo, { toValue: 1, duration: 1000, useNativeDriver: true });
anim.start(() => console.log(_foo));
}
useEffect(() => {
foo.addListener(_onChangeFoo);
showFoo();
return () => foo.removeListener(_onChangeFoo);
});
return <View />;
}
import React from 'react';
import { Animated, View } from 'react-native';
class ClassBar extends React.Component {
constructor(props) {
super(props);
this.state = { foo: new Animated.Value(0) };
this._foo = 0;
this._onChangeFoo = this._onChangeFoo.bind(this);
}
componentDidMount() {
this.state.foo.addListener(this._onChangeFoo);
this.showFoo();
}
componentWillUnmount() {
this.state.foo.removeListener(this._onChangeFoo);
}
showFoo() {
let anim = Animated.timing(this.state.foo, { toValue: 1, duration: 1000, useNativeDriver: true });
anim.start(() => console.log(this._foo));
}
_onChangeFoo({ value }) {
this._foo = value;
}
render() {
return <View />;
}
}
答案 0 :(得分:6)
useRef
钩不仅用于DOM引用,还可以存储您喜欢的任何可变值。
示例
function FunctionalBar(props) {
const [foo] = useState(new Animated.Value(0));
const _foo = useRef(0);
function showFoo() {
let anim = Animated.timing(foo, { toValue: 1, duration: 1000, useNativeDriver: true });
anim.start(() => console.log(_foo.current));
}
useEffect(() => {
function _onChangeFoo({ value }) {
_foo.current = value;
}
foo.addListener(_onChangeFoo);
showFoo();
return () => foo.removeListener(_onChangeFoo);
}, []);
return <View />;
}
答案 1 :(得分:1)
const a = useRef(5) // 5 is initial value
a.current
a.current = my_value
答案 2 :(得分:0)
这是一个非常不寻常的示例,但是,如果我正确地阅读了此示例,则只想在每次组件安装时存储唯一的_foo
对象,并在卸载时销毁它们,而且还可以防止在此值时额外渲染变化。
我之前遇到过这种情况,简单对象(map / hash)应该可以解决问题:
let foos = {}
let fooCount = 0
function F(props) {
useEffect(() => {
let fooId = fooCount++
foos[fooId] = new Animated.Value(0)
foos[fooId].addListener(...)
return () => foos[fooId].removeListener(...)
}, []) // <-- do not rerun when called again (only when unmounted)
...render...
}
或类似的东西。如果您有一个可运行的示例,可以对其进行调整以使其更适合您的示例。无论哪种方式,大多数具有范围问题的事物都可以通过基元来解决。
答案 3 :(得分:0)
只是为了支持Tholle,这是官方文档
但是,
useRef()
不仅对ref属性有用。它的 便于保持任何可变的价值(类似于您的使用方式) 类中的实例字段。之所以可行,是因为
useRef()
创建了一个纯JavaScript对象。的useRef()
与创建{current: ...}
对象之间的唯一区别 你自己是useRef
会在每个 渲染。请注意,
useRef
的内容更改时不会通知您。 更改.current属性不会导致重新渲染。如果你想 在React将引用附加或分离到DOM节点时运行一些代码, 您可能要改用回调引用。
答案 4 :(得分:0)
我很幸运地使用 useRef
钩子和解构(+ 一个可选的变量别名“my”),然后你将所有值保存在 my
对象中,这样你就不会必须使用多个引用或一直使用 myref.current
:
function MyComponent(props) {
const componentRef = useRef({});
const { current: my } = componentRef;
my.count = 42;
console.log(my.count); // 42
my.greet = "hello";
console.log(my.greet); // hello
return <div />;
}