admin管理员组文章数量:1321254
I'm trying to get AsyncStorage working in react-native, just to save some user inputted data. Although I've found some help through online resources and the SO munity, this stuff is driving me crazy.
Even the React docs seem flawed. The code below is taken straight from the AsyncStorage page of the react docs and pasted into a new, clean application (I've added the final line of code to register the app, it won't work without it).
The big block of code below is posted as reference. I believe the important bit is this line:
{this.state.messages.map(function(m) {
return <Text key={m}>{m}</Text>;
})}
I get unique key errors, although I have a key set.
'use strict';
var React = require('react');
var ReactNative = require('react-native');
var {
AppRegistry,
AsyncStorage,
PickerIOS,
Text,
View
} = ReactNative;
var PickerItemIOS = PickerIOS.Item;
var STORAGE_KEY = '@AsyncStorageExample:key';
var COLORS = ['red', 'orange', 'yellow', 'green', 'blue'];
var BasicStorageExample = React.createClass({
ponentDidMount() {
this._loadInitialState().done();
},
async _loadInitialState() {
try {
var value = await AsyncStorage.getItem(STORAGE_KEY);
if (value !== null){
this.setState({selectedValue: value});
this._appendMessage('Recovered selection from disk: ' + value);
} else {
this._appendMessage('Initialized with no selection on disk.');
}
} catch (error) {
this._appendMessage('AsyncStorage error: ' + error.message);
}
},
getInitialState() {
return {
selectedValue: COLORS[0],
messages: [],
};
},
render() {
var color = this.state.selectedValue;
return (
<View>
<PickerIOS
selectedValue={color}
onValueChange={this._onValueChange}>
{COLORS.map((value) => (
<PickerItemIOS
key={value}
value={value}
label={value}
/>
))}
</PickerIOS>
<Text>
{'Selected: '}
<Text style={{color}}>
{this.state.selectedValue}
</Text>
</Text>
<Text>{' '}</Text>
<Text onPress={this._removeStorage}>
Press here to remove from storage.
</Text>
<Text>{' '}</Text>
<Text>Messages:</Text>
{this.state.messages.map(function(m) {
return <Text key={m}>{m}</Text>;
})}
</View>
);
},
async _onValueChange(selectedValue) {
this.setState({selectedValue});
try {
await AsyncStorage.setItem(STORAGE_KEY, selectedValue);
this._appendMessage('Saved selection to disk: ' + selectedValue);
} catch (error) {
this._appendMessage('AsyncStorage error: ' + error.message);
}
},
async _removeStorage() {
try {
await AsyncStorage.removeItem(STORAGE_KEY);
this._appendMessage('Selection removed from disk.');
} catch (error) {
this._appendMessage('AsyncStorage error: ' + error.message);
}
},
_appendMessage(message) {
this.setState({messages: this.state.messages.concat(message)});
},
});
exports.title = 'AsyncStorage';
exports.description = 'Asynchronous local disk storage.';
exports.examples = [
{
title: 'Basics - getItem, setItem, removeItem',
render(): ReactElement { return <BasicStorageExample />; }
},
];
AppRegistry.registerComponent('BasicStorageExample', () => BasicStorageExample);
The above code works until you select an element that you have selected before. Then you're riddled with console errors about unique child keys. I haven't been able to figure out how to avoid this.
Console errors read:
index.ios.bundle:24458Warning: flattenChildren(...): Encountered two children with the same key, '6:$Saved selection to disk: orange'. Child keys must be unique; when two children share a key, only the first child will be used.
I'm trying to get AsyncStorage working in react-native, just to save some user inputted data. Although I've found some help through online resources and the SO munity, this stuff is driving me crazy.
Even the React docs seem flawed. The code below is taken straight from the AsyncStorage page of the react docs and pasted into a new, clean application (I've added the final line of code to register the app, it won't work without it).
The big block of code below is posted as reference. I believe the important bit is this line:
{this.state.messages.map(function(m) {
return <Text key={m}>{m}</Text>;
})}
I get unique key errors, although I have a key set.
'use strict';
var React = require('react');
var ReactNative = require('react-native');
var {
AppRegistry,
AsyncStorage,
PickerIOS,
Text,
View
} = ReactNative;
var PickerItemIOS = PickerIOS.Item;
var STORAGE_KEY = '@AsyncStorageExample:key';
var COLORS = ['red', 'orange', 'yellow', 'green', 'blue'];
var BasicStorageExample = React.createClass({
ponentDidMount() {
this._loadInitialState().done();
},
async _loadInitialState() {
try {
var value = await AsyncStorage.getItem(STORAGE_KEY);
if (value !== null){
this.setState({selectedValue: value});
this._appendMessage('Recovered selection from disk: ' + value);
} else {
this._appendMessage('Initialized with no selection on disk.');
}
} catch (error) {
this._appendMessage('AsyncStorage error: ' + error.message);
}
},
getInitialState() {
return {
selectedValue: COLORS[0],
messages: [],
};
},
render() {
var color = this.state.selectedValue;
return (
<View>
<PickerIOS
selectedValue={color}
onValueChange={this._onValueChange}>
{COLORS.map((value) => (
<PickerItemIOS
key={value}
value={value}
label={value}
/>
))}
</PickerIOS>
<Text>
{'Selected: '}
<Text style={{color}}>
{this.state.selectedValue}
</Text>
</Text>
<Text>{' '}</Text>
<Text onPress={this._removeStorage}>
Press here to remove from storage.
</Text>
<Text>{' '}</Text>
<Text>Messages:</Text>
{this.state.messages.map(function(m) {
return <Text key={m}>{m}</Text>;
})}
</View>
);
},
async _onValueChange(selectedValue) {
this.setState({selectedValue});
try {
await AsyncStorage.setItem(STORAGE_KEY, selectedValue);
this._appendMessage('Saved selection to disk: ' + selectedValue);
} catch (error) {
this._appendMessage('AsyncStorage error: ' + error.message);
}
},
async _removeStorage() {
try {
await AsyncStorage.removeItem(STORAGE_KEY);
this._appendMessage('Selection removed from disk.');
} catch (error) {
this._appendMessage('AsyncStorage error: ' + error.message);
}
},
_appendMessage(message) {
this.setState({messages: this.state.messages.concat(message)});
},
});
exports.title = 'AsyncStorage';
exports.description = 'Asynchronous local disk storage.';
exports.examples = [
{
title: 'Basics - getItem, setItem, removeItem',
render(): ReactElement { return <BasicStorageExample />; }
},
];
AppRegistry.registerComponent('BasicStorageExample', () => BasicStorageExample);
The above code works until you select an element that you have selected before. Then you're riddled with console errors about unique child keys. I haven't been able to figure out how to avoid this.
Console errors read:
Share Improve this question edited Jun 1, 2016 at 21:04 bruh asked Jun 1, 2016 at 20:51 bruhbruh 2,3058 gold badges34 silver badges44 bronze badgesindex.ios.bundle:24458Warning: flattenChildren(...): Encountered two children with the same key, '6:$Saved selection to disk: orange'. Child keys must be unique; when two children share a key, only the first child will be used.
2 Answers
Reset to default 3If you use the message text as the key, and you have two messages with the same text, then the key is not unique. You should use the array index as a key:
{this.state.messages.map((message, i) => (
<Text key={i}>
{message}
</Text>
)}
As a side note, you should make the following changes to your code:
- Use the new React ES6 syntax instead of the old
React.createClass
- Use ES6
import
instead ofrequire()
'use strict'
is pletely redundant in ES6 because it's strict by default- This is much more opinionated but you should use ESLint with something like AirBnb JS style guide. It integrates smoothly to Atom using AtomLinter.
- But kudos on the async/await! :)
Leverage the index, rather than the value, within your map function.
{this.state.messages.map(function(m, i) {
return <Text key={'message-' + i}>{m}</Text>;
})}
本文标签: javascriptReact Native setting keys on elementsStack Overflow
版权声明:本文标题:javascript - React Native setting keys on elements - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1742097031a2420614.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论