我刚刚更新以反应原生0.54.0,其中还包括反应16.3的alpha 1,我自然会收到很多关于componentWillMount
和componentWillReceiveProps
折旧的警告。
我有一个依赖于componentWillReceiveProps
核心的动画路线组件,它接收新路径,将其与之前的路径进行比较,如果它们设置了旧子项,将它们设置为动画,设置新子项并将它们设置为动画
以下是有问题的代码:
componentWillReceiveProps(nextProps: Props) {
if (nextProps.pathname !== this.props.pathname) {
this.setState({ previousChildren: this.props.children, pointerEvents: false }, () =>
this.animate(0)
);
}
}
现在我有关于将此移植到static getDerivedStateFromProps
1)我无法访问this.props
,因此无法访问以前的路径名,我想我可以将这些道具存储在状态中,这是正确的方法吗?似乎重复数据。
2)因为我无法访问this
我无法调用我的动画功能,而是依赖于状态。我怎么能绕过这个?
3)我需要首先设置状态,然后调用动画,因为getDerivedStateFromProps
通过返回值设置状态,之后我不能做很多事情,所以有没有办法设置状态和之后那已经完成了回调?
4)pathname
位目前仅用于componentWillreceiveProps
,如果我将其移至州并且永远不会在this.state
内使用getDerivedStateFromProps
(因为我可以'} t)this.state.pathname
错误定义但从未使用过。这里最好的方法是使它静止吗?
我的第一直觉是将其更改为componentDidUpdate
,但我们不应该在其中使用setState
正确吗? (这在我的场景中确实有用)。
componentDidUpdate(prevProps: Props) {
if (this.props.pathname !== prevProps.pathname) {
this.setState({ previousChildren: prevProps.children, pointerEvents: false }, () =>
this.animate(0)
);
}
}
注意:据我所知,我认为有一个功能正在进入"悬疑"这将允许我们保持视图安装在组件卸载事件?我无法找到任何对此的引用,但这听起来像是我可以用于此动画的东西
对于任何有兴趣的人,这是一个有问题的完整组件的片段
// @flow
import React, { Component, type Node } from "react";
import { Animated } from "react-native";
type Props = {
pathname: string,
children: Node
};
type State = {
animation: Animated.Value,
previousChildren: Node,
pointerEvents: boolean
};
class OnboardingRouteAnomation extends Component<Props, State> {
state = {
animation: new Animated.Value(1),
previousChildren: null,
pointerEvents: true
};
componentWillReceiveProps(nextProps: Props) {
if (nextProps.pathname !== this.props.pathname) {
this.setState({ previousChildren: this.props.children, pointerEvents: false }, () =>
this.animate(0)
);
}
}
animate = (value: 0 | 1) => {
Animated.timing(this.state.animation, {
toValue: value,
duration: 150
}).start(() => this.animationLogic(value));
};
animationLogic = (value: 0 | 1) => {
if (value === 0) {
this.setState({ previousChildren: null, pointerEvents: true }, () => this.animate(1));
}
};
render() {
const { animation, previousChildren, pointerEvents } = this.state;
const { children } = this.props;
return (
<Animated.View
pointerEvents={pointerEvents ? "auto" : "none"}
style={{
alignItems: "center",
opacity: animation.interpolate({ inputRange: [0, 1], outputRange: [0, 1] }),
transform: [
{
scale: animation.interpolate({ inputRange: [0, 1], outputRange: [0.94, 1] })
}
]
}}
>
{previousChildren || children}
</Animated.View>
);
}
}
export default OnboardingRouteAnomation;
答案 0 :(得分:12)
使用react版本16.3,使用componentWillReceiveProps
很好,但会导致在控制台中显示弃用警告。 It will be removed in version 17。 FWIW Dan Abramov has warned against using alpha functionality in production - 但这是在2018年3月回来的。
让我们来看看你的问题:
1)我不再能访问this.props,因此无法访问以前的路径名,我想我可以将这些道具存放在状态中。这是正确的方法吗?似乎重复数据。
是的。
如果要更新/重新渲染组件,则应合并props
和state
。在您的情况下,您希望在使用生命周期方法更改pathname
时更新组件/触发器动画。
似乎重复数据。
检查一下:React Team post on State and Lifecycle
2)因为我无法访问这个,所以我无法调用依赖于状态的动画功能。我怎么能绕过这个?
<强> componentDidUpdate 强>
在每个重新渲染周期中渲染完成后,将调用此函数。这意味着您可以确保组件及其所有子组件已正确呈现。
这意味着您可以在animate
setState
之后致电componentDidUpdate
3)我需要先设置状态,然后调用动画,因为getDerivedStateFromProps通过返回值来设置状态,之后我做不了多少,所以有没有办法设置状态,然后执行完成后执行a回调?
参见第2点(Use componentDidUpdate)
4)pathname位目前仅在componentWillreceiveProps中使用,如果我将其移动到state并且从不在getDerivedStateFromProps中使用this.state(因为我不能)将this.state.pathname错误定义为但从未使用过。这里最好的方法是使它静止吗?
不,它将由componentDidUpdate
使用以下是我如何做到这一点:
// @flow
import React, { Component, type Node } from "react";
type Props = {
pathname: string,
children: Node
};
type State = {
previousChildren: Node,
pointerEvents: boolean
};
class OnboardingRouteAnomation extends Component<Props, State> {
state = {
previousChildren: null,
pointerEvents: true,
pathname: ''
};
static getDerivedStateFromProps(nextProps, prevState) {
if (nextProps.pathname !== prevState.pathname) {
return {
previousChildren: nextProps.children,
pointerEvents: false,
pathname: nextProps.pathname
};
}
return null;
}
componentDidUpdate(prevProps, prevState) {
if (prevState.pathname !== this.state.pathname){
console.log("prevState.pathname", prevState.pathname);
console.log("this.props.pathname", this.props.pathname);
this.animate(0);
}
}
componentDidMount(){
this.setState({ pathname: this.props.pathname});
}
animate = (value: 0 | 1) => {
console.log("this animate called", this);
animationLogic(value);
};
animationLogic = (value: 0 | 1) => {
if (value === 0) {
this.setState({ previousChildren: null, pointerEvents: true }, () => this.animate(1));
}
};
render() {
const { animation, previousChildren, pointerEvents } = this.state;
const { children } = this.props;
return (
<div>
{this.props.children}
</div>
);
}
}
export default OnboardingRouteAnomation;
我相信这是反应开发者应该如何处理的。你应该
通过componentDidUpdate
更新后调用动画,因为它有副作用。
我使用更具描述性的名称来表示路径已更改。像isPathUpdated
这样的东西。然后,您可以animate
检查isPathUpdated
作为切换。