【发布时间】:2019-03-06 15:54:53
【问题描述】:
我有一个受控输入,它接受一个名为 user 的道具。该对象由其父组件传递给它,在该组件中使用观察者异步初始化1。
在父组件中:
onAuthStateChanged() {
this.unregisterAuthObserver = onAuthStateChanged((user) => {
this.setState({
isSignedIn: Boolean(user),
user,
});
});
}
我想用user.displayName 填充受控输入的初始状态。像下面这样的东西,这不应该是一个反模式,因为状态只依赖于 prop user 的构造。
class ControlledInput extends Component {
constructor(props) {
super(props);
const { user } = props;
this.state = {
displayName: user ? user.displayName : '',
};
}
}
当我刷新受控输入时,出现以下问题:
-
user的值是undefined,因为观察者尚未触发。组件构建完成,displayName分配给''。 - 观察者触发,
user被分配一个复杂对象,React 重新渲染组件。这不会改变组件的状态,displayName仍然是''。
我不知道如何利用组件生命周期方法来实现这一点。这种情况有最佳实践吗?我什至应该依赖异步道具,还是应该将观察者移动到受控组件中?
我考虑过使用componentDidUpdate() 来确定何时分配user,但感觉就像一个黑客。
当组件更新时,以此为契机对 DOM 进行操作。只要您将当前的 props 与以前的 props 进行比较,这也是进行网络请求的好地方(例如,如果 props 没有更改,则可能不需要网络请求)。
1 观察者是 Firebase 身份验证的一部分,但我不确定这与问题是否相关。
【问题讨论】:
-
为什么不在
OnAuthStateChanged的状态中添加displayName: user ? user.displayName : '',?setState? -
你能发布你的渲染函数(实际上是整个组件)吗?您如何将更改传达给
user到displayName? -
@ColinYoung 这是使用 React Router 中
Route组件的包装器完成的:<ProtectedRoute path="/controlledInput" render={() => <ControlledInput user={user} />} ... />。 -
@JamesPoag 我不确定这会解决我遇到的问题。在构造受控输入时,
displayName仍为空。
标签: reactjs firebase firebase-authentication