Ниже приведены два компонента 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 />;
}
}