React Native 问题 - 通过从构造函数调用另一个方法来初始化状态
React Native Issue - Initialize state by calling another method from constructor
我有一个小型 React Native 组件,我尝试通过从本地存储读取值来初始化状态 (AsyncStorage)。但是当我从构造函数调用外部方法时,我得到 undefined 作为状态值。
这是我的部分代码:
constructor(props) {
super(props);
this.state = {
languageChecked: I18n.locale,
anonymityChecked: this.pickLocalKey('anonymity', true),
locationChecked: this.pickLocalKey('location', false),
notificationChecked: this.pickLocalKey('notification', false),
statisticsChecked: this.pickLocalKey('statistics', false),
};
console.log("STATE: " + this.state.anonymityChecked); // UNDEFINED
}
pickLocalKey(key, defaultValue) {
AsyncStorage.getItem(key).then((value) => {
const item = (value !== null && value !== undefined) ? value : defaultValue;
console.log(item);
return item;
});
}
有谁知道如何解决这个问题?
提前谢谢你
替换
pickLocalKey(key, defaultValue) {
AsyncStorage.getItem(key).then((value) => {
const item = (value !== null && value !== undefined) ? value : defaultValue;
console.log(item);
return item;
});
}
和
constructor(props) {
super(props);
this.pickLocalKey('anonymity', true, 'anonymityChecked');
this.pickLocalKey('location', false, 'locationChecked');
this.pickLocalKey('notification', false, 'notificationChecked');
this.pickLocalKey('statistics', false, 'statisticsChecked')
this.state = {
};
}
pickLocalKey = (key, defaultValue, stateKey) => {
AsyncStorage.getItem(key).then((value) => {
const item = (value !== null && value !== undefined) ? value : defaultValue;
console.log(item);
this.setState({
[stateKey]: item
});
});
}
render() {
console.log(this.state);
}
编辑:
所以问题是这是一个承诺,现在构造函数 运行 一次,不会等待你的承诺来解决。你也不能或不想让你的构造函数成为一个承诺。取回数据后,设置数据不可用。
但是你调用函数然后做setState。然后在render中查看状态,希望你看到的是正确的状态。
您在问题中粘贴的代码存在几个问题。
首先,constructor
是同步的,您试图在其中执行异步任务。这不是一个好主意。
如果您需要从 AsyncStorage
加载值并将它们存储在 state
中,您应该在 componentDidMount
中执行
因此在构造函数中设置初始值,添加一个附加值loaded: false
。这在以后会变得很重要。
constructor (props) {
super(props);
this.state = {
languageChecked: I18n.locale,
anonymityChecked: true,
locationChecked: false,
notificationChecked: false,
statisticsChecked: false,
loaded: false // <- add this additional value
};
}
目前您的 pickLocalKey
函数实际上没有 returning 任何东西。 return 值被困在承诺中。幸运的是,我们可以将函数转换为使用 async/await
。所以它应该看起来像这样:
pickLocalKey = async (key, defaultValue) => {
try {
let value = await AsyncStorage.getItem(key);
const item = (value !== null && value !== undefined) ? value : defaultValue;
return item === 'true'; // this will make sure we get a Boolean back as long as you store strings 'true' and 'false' for your Booleans
} catch (error) {
return defaultValue;
}
}
请注意 await
可以抛出,因此最好将其包装在 try/catch
中。
然后在您的 componentDidMount
中,您应该进行调用以从 AsyncStorage
中检索值
async componentDidMount () {
// these won't throw as we are catching the error before it gets here
let anonymityChecked = await this.pickLocalKey('anonymity', true);
let locationChecked = await this.pickLocalKey('location', false);
let notificationChecked = await this.pickLocalKey('notification', false);
let statisticsChecked = await this.pickLocalKey('statistics', false);
// set all items in state in one go as multiple calls to setState are not good
this.setState({
anonymityChecked,
locationChecked,
notificationChecked,
statisticsChecked,
loaded: true . // <- we set loaded to true
}, () => console.log(this.state)); // this is how you check state after it has been set
}
然后在您的 render
中,您现在应该使用 loaded
现在为 true 的事实来呈现正确的视图:
render () {
if (this.state.loaded) {
return (
this is the view that you actually want to show
)
} else {
return (
this is the view that you will show when everything is loading
)
}
}
以下是一些值得一读的文章:
- https://medium.com/@bluepnume/learn-about-promises-before-you-start-using-async-await-eb148164a9c8
- https://medium.learnreact.com/setstate-is-asynchronous-52ead919a3f0
- https://medium.learnreact.com/setstate-takes-a-callback-1f71ad5d2296
- https://medium.learnreact.com/setstate-takes-a-function-56eb940f84b6
我有一个小型 React Native 组件,我尝试通过从本地存储读取值来初始化状态 (AsyncStorage)。但是当我从构造函数调用外部方法时,我得到 undefined 作为状态值。
这是我的部分代码:
constructor(props) {
super(props);
this.state = {
languageChecked: I18n.locale,
anonymityChecked: this.pickLocalKey('anonymity', true),
locationChecked: this.pickLocalKey('location', false),
notificationChecked: this.pickLocalKey('notification', false),
statisticsChecked: this.pickLocalKey('statistics', false),
};
console.log("STATE: " + this.state.anonymityChecked); // UNDEFINED
}
pickLocalKey(key, defaultValue) {
AsyncStorage.getItem(key).then((value) => {
const item = (value !== null && value !== undefined) ? value : defaultValue;
console.log(item);
return item;
});
}
有谁知道如何解决这个问题? 提前谢谢你
替换
pickLocalKey(key, defaultValue) {
AsyncStorage.getItem(key).then((value) => {
const item = (value !== null && value !== undefined) ? value : defaultValue;
console.log(item);
return item;
});
}
和
constructor(props) {
super(props);
this.pickLocalKey('anonymity', true, 'anonymityChecked');
this.pickLocalKey('location', false, 'locationChecked');
this.pickLocalKey('notification', false, 'notificationChecked');
this.pickLocalKey('statistics', false, 'statisticsChecked')
this.state = {
};
}
pickLocalKey = (key, defaultValue, stateKey) => {
AsyncStorage.getItem(key).then((value) => {
const item = (value !== null && value !== undefined) ? value : defaultValue;
console.log(item);
this.setState({
[stateKey]: item
});
});
}
render() {
console.log(this.state);
}
编辑: 所以问题是这是一个承诺,现在构造函数 运行 一次,不会等待你的承诺来解决。你也不能或不想让你的构造函数成为一个承诺。取回数据后,设置数据不可用。 但是你调用函数然后做setState。然后在render中查看状态,希望你看到的是正确的状态。
您在问题中粘贴的代码存在几个问题。
首先,constructor
是同步的,您试图在其中执行异步任务。这不是一个好主意。
如果您需要从 AsyncStorage
加载值并将它们存储在 state
中,您应该在 componentDidMount
因此在构造函数中设置初始值,添加一个附加值loaded: false
。这在以后会变得很重要。
constructor (props) {
super(props);
this.state = {
languageChecked: I18n.locale,
anonymityChecked: true,
locationChecked: false,
notificationChecked: false,
statisticsChecked: false,
loaded: false // <- add this additional value
};
}
目前您的 pickLocalKey
函数实际上没有 returning 任何东西。 return 值被困在承诺中。幸运的是,我们可以将函数转换为使用 async/await
。所以它应该看起来像这样:
pickLocalKey = async (key, defaultValue) => {
try {
let value = await AsyncStorage.getItem(key);
const item = (value !== null && value !== undefined) ? value : defaultValue;
return item === 'true'; // this will make sure we get a Boolean back as long as you store strings 'true' and 'false' for your Booleans
} catch (error) {
return defaultValue;
}
}
请注意 await
可以抛出,因此最好将其包装在 try/catch
中。
然后在您的 componentDidMount
中,您应该进行调用以从 AsyncStorage
async componentDidMount () {
// these won't throw as we are catching the error before it gets here
let anonymityChecked = await this.pickLocalKey('anonymity', true);
let locationChecked = await this.pickLocalKey('location', false);
let notificationChecked = await this.pickLocalKey('notification', false);
let statisticsChecked = await this.pickLocalKey('statistics', false);
// set all items in state in one go as multiple calls to setState are not good
this.setState({
anonymityChecked,
locationChecked,
notificationChecked,
statisticsChecked,
loaded: true . // <- we set loaded to true
}, () => console.log(this.state)); // this is how you check state after it has been set
}
然后在您的 render
中,您现在应该使用 loaded
现在为 true 的事实来呈现正确的视图:
render () {
if (this.state.loaded) {
return (
this is the view that you actually want to show
)
} else {
return (
this is the view that you will show when everything is loading
)
}
}
以下是一些值得一读的文章:
- https://medium.com/@bluepnume/learn-about-promises-before-you-start-using-async-await-eb148164a9c8
- https://medium.learnreact.com/setstate-is-asynchronous-52ead919a3f0
- https://medium.learnreact.com/setstate-takes-a-callback-1f71ad5d2296
- https://medium.learnreact.com/setstate-takes-a-function-56eb940f84b6