我想从另一个函数中的值访问值。这两个函数在同一作用域内,而不是嵌套的。
我尝试仅使用一个函数ComponentDidMount()并增加了外部查询的范围,以便可以在内部访问该值。它可以工作,但在控制台中始终显示错误,但显示正确。我认为这是因为我对多个事物使用相同的引用。但是,如果我缩小范围,但仍将其保留为一个功能,它将无法正常工作。我认为这与创建两个函数并且无法访问另一个函数中的值相同。但是我不明白,尽管我在第一个函数内部设置了值的状态。为什么它会在我在构造函数中初始化的第二个参数中恢复默认值?
这就是我现在所拥有的。请注意,ComponentWillMount可以是任何其他函数。
componentWillMount = () => {
let query = [];
this.unsub = this.props.firebase.users().doc(this.props.firebase.userId()).get().then(doc => {
query.push(doc.data().LinkedUsername)
const lU = this.props.firebase.users().where("email", "==", query[0])
lU.get().then(snapshot => {
// console.log(snapshot.docs[0].id)
this.setState({queryId: snapshot.docs[0].id});
console.log(this.state.queryId)
})
})
}
componentDidMount = () => {
this.setState({loading: true});
console.log(this.state.queryId)
this.unsubscribe = this.props.firebase
.users().doc(this.props.firebase.userId()).collection('tasks')
.onSnapshot(snapshot => {
let items = [];
snapshot.forEach(doc =>
(doc.data().status === false) ?
items.push({...doc.data(), uid: doc.id})
:
null
);
this.setState({
items,
loading: false,
});
});
}
记下控制台位置。第一个控制台返回所需的值,但第二个则不。它返回未定义的值或在构造函数中初始化时分配的值,如下所示
constructor(props) {
super(props);
this.state = {
loading: false,
items: [],
// queryId: null
};
this.classes = props;
}
如果我在下面进行操作,它会在屏幕上提供所需的输出,但会在控制台中多次抛出相同的错误。
componentDidMount = () => {
this.setState({loading: true});
console.log(this.state.queryId)
let query = [];
this.unsub = this.props.firebase.users().doc(this.props.firebase.userId()).get().then(doc => {
query.push(doc.data().LinkedUsername)
const lU = this.props.firebase.users().where("email", "==", query[0])
lU.get().then(snapshot => {
// console.log(snapshot.docs[0].id)
this.setState({queryId: snapshot.docs[0].id});
console.log(this.state.queryId)
this.unsubscribe = this.props.firebase
.users().doc(this.props.firebase.userId()).collection('tasks')
.onSnapshot(snapshot => {
let items = [];
snapshot.forEach(doc =>
(doc.data().status === false) ?
items.push({...doc.data(), uid: doc.id})
:
null
);
this.setState({
items,
loading: false,
});
});
})
})
}
但是,如果我在下面进行操作,则不会。检查倒数第二行和倒数第三行括号的位置差异。
constructor(props) {
super(props);
this.state = {
loading: false,
items: [],
// queryId: null
};
this.classes = props;
}
如果我在下面进行操作,它会在屏幕上提供所需的输出,但会在控制台中多次抛出相同的错误。
componentDidMount = () => {
this.setState({loading: true});
console.log(this.state.queryId)
let query = [];
this.unsub = this.props.firebase.users().doc(this.props.firebase.userId()).get().then(doc => {
query.push(doc.data().LinkedUsername)
const lU = this.props.firebase.users().where("email", "==", query[0])
lU.get().then(snapshot => {
// console.log(snapshot.docs[0].id)
this.setState({queryId: snapshot.docs[0].id});
console.log(this.state.queryId)
})
})
this.unsubscribe = this.props.firebase
.users().doc(this.props.firebase.userId()).collection('tasks')
.onSnapshot(snapshot => {
let items = [];
snapshot.forEach(doc =>
(doc.data().status === false) ?
items.push({...doc.data(), uid: doc.id})
:
null
);
this.setState({
items,
loading: false,
});
});
}
实际结果
undefined index.js:43
Qz1mFFBgPrUFPfO1YFqVxfVpAbE2 index.js:36
预期结果
Qz1mFFBgPrUFPfO1YFqVxfVpAbE2 index.js:43
Qz1mFFBgPrUFPfO1YFqVxfVpAbE2 index.js:36
答案 0 :(得分:0)
componentDidMount()
在初始渲染后被调用。
setState()
是异步调用。
因此,基本上,当您调用componentWillMount()
setState()
并且状态值被更新时,componentDidMount()
已经被调用。
避免在构造函数或componentWillMount()
中调用或使用api
您的网络请求应位于componentDidMount()
答案 1 :(得分:0)
正如@Ravi所说,您不应在componentWillMount
内调用网络请求。您可以在componentDidMount
内部安全地调用网络请求。
在您的第一个代码段中,您正在this.setState()
中调用componentWillMount()
,并在firebase响应后设置状态。从Firebase获取数据并获得响应后需要设置状态。
componentDidMount()
将在组件安装后立即被调用。从Firebase获取数据并将其设置为componentWillMount()
的状态会花费一些时间,第二个console.log()
将为您提供undefined
或初始化时分配的任何内容在构造函数中。
在第二个代码段中,您的构造函数如下:
constructor(props) {
super(props);
this.state = {
loading: false,
items: [],
// queryId: null
};
this.classes = props;
}
正如您在构造函数中注释了queryId
并将其记录在componentDidMount()
中一样,由于未初始化,它将抛出错误或在控制台中给您undefined
在构造函数中。
由于React / ReactNative是一个声明性框架,即您仅告诉React / ReactNative需要什么,而无需担心如何做,因此可以按照以下方法进行网络请求,并且当状态更改时,所有状态值将为在整个组件内部进行了更新:
constructor(props) {
super(props);
this.state = {
loading: true,
items: [],
queryId: null
};
}
componentDidMount = () => {
//your network request
fetch('fetch_url')
.then((response) => response.json())
.then((response) => {
this.setState({ //making result to be globally accessible
loading: false,
items: response.items,
queryId: response.queryId
});
})
.catch((error) => {
//handle error
})
}
但是,如果要一个接一个地执行多个请求,则可以使用async/await
,也可以制作一系列then
语句,如下所示:
fetch('fetch_url')
.then((response) => response.json())
.then((response) => {
this.setState({ //making result to be globally accessible
loading: false,
items: response.items,
queryId: response.queryId
});
return response.queryId;
})
.then((response) => { //'queryId' returned from the upper 'then'
//other operations
})
.catch((error) => {
//handle error
})