zip*_*zit 3 reactjs react-native
我正在努力学习React-Native.我正在看一个Joshua Sierles的响应式图像网格示例.(谢谢Joshua!)在这个示例中,Joshua使用React以可控的方式在移动显示屏上小心地放置图像元素.注意:他只使用三张图像,并在文档中重复多次.不幸的是,如上所述,该示例生成警告:
警告:数组或迭代器中的每个子节点都应该具有唯一的"键"支柱.检查渲染方法
YourProjectNameHere.有关更多信息,请参见 fb.me/react-warning-keys.(从缩短的形式推断出的链接......)
我完全理解一行中的每个元素和React生成的每一行必须具有唯一的键属性. 我不清楚的是如何做到这一点.这是我的黑客/解决方案. key={Math.random()}
这个hack工作正常,但它似乎是......错了.这里的问题是,识别单个图像ID以及识别单个行ID的正确方法是什么?
'use strict';
var React = require('react-native');
var {
AppRegistry,
StyleSheet,
Text,
View,
Image,
Dimensions,
ScrollView
} = React;
var _ = require('lodash');
var {width, height} = Dimensions.get('window');
var IMAGE_URLS = _.flatten(_.times(9, () => {return ['http://rnplay.org/IMG_0599.jpg', 'http://rnplay.org/IMG_0602.jpg', 'http://rnplay.org/IMG_0620.jpg']})); // 9 x 3 = 27 images
var IMAGES_PER_ROW = 4;
var AwesomeProject1 = React.createClass({
getInitialState() {
return {
currentScreenWidth: width,
currentScreenHeight: height
}
},
handleRotation(event) {
var layout = event.nativeEvent.layout
this.setState({currentScreenWidth: layout.width, currentScreenHeight: layout.height })
},
calculatedSize() {
var size = this.state.currentScreenWidth / IMAGES_PER_ROW
return {width: size, height: size}
},
// note: I added key={Math.random()} in two places below.
// Its a BS fix, but it seems to work to avoid the warning message.
renderRow(images) {
return images.map((uri) => {
return (
<Image style={[styles.image, this.calculatedSize()]} key={Math.random()} source={{uri: uri}} /> //key={Math.random()}
)
})
},
renderImagesInGroupsOf(count) {
return _.chunk(IMAGE_URLS, IMAGES_PER_ROW).map((imagesForRow) => {
return (
<View style={styles.row} key={Math.random()}>
{this.renderRow(imagesForRow)}
</View>
)
})
},
render: function() {
return (
<ScrollView onLayout={this.handleRotation} contentContainerStyle={styles.scrollView}>
{this.renderImagesInGroupsOf(IMAGES_PER_ROW)}
</ScrollView>
);
}
});
var styles = StyleSheet.create({
row: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'flex-start'
},
image: {
}
});
AppRegistry.registerComponent('AwesomeProject1', () => AwesomeProject1);
Run Code Online (Sandbox Code Playgroud)
我已经尝试key=uri.id , imagesForRow.id, images.id, etc了我能想到的每一种组合.无效与随机数功能一样好.其他想法?这样做的正确方法是什么?
根据Chris Geirman的回答更新如下:我想展示我的最终代码.
renderRow(images) {
return images.map((uri, idx) => {
return (
<Image style={[styles.image, this.calculatedSize()]} key={uri.concat(idx)} source={{uri: uri}} /> //key={Math.random()}
)
})
},
renderImagesInGroupsOf(count) {
return _.chunk(IMAGE_URLS, IMAGES_PER_ROW).map((imagesForRow, idx2) => {
return (
<View style={styles.row} key={imagesForRow.concat(idx2)}>
{this.renderRow(imagesForRow)}
</View>
)
})
},
Run Code Online (Sandbox Code Playgroud)
我认为,如果要移动组件(例如更改顺序)或预先添加元素,关键只是真正相关.如果这对您来说不是问题,而您只想使警告静音,则可以使用数组索引(第二个arg map()).
React Docs的简短官方解释在React Docs - Listing Mutations中.
我将扩展这一点,因为我相信你接受的另一个答案是误导性的:不是一个合理的解决方案,因为它呈现出来.
我的理解是,React将一个元素子元素解释为一个特殊情况,其中元素的长度或相对位置可能会在需要保留组件实例时发生变化.在React文档中,他们描述如下:
当孩子们被洗牌时(如在搜索结果中)或者如果新组件被添加到列表的前面(如在流中).
但是,通常使用数组只是为了方便脚本生成子项,否则可以按字面/静态表示.这就是我认为你在这里的情况.如果不是这种情况,您将需要并且可能已经具有合法的唯一ID.例如,如果我正确理解您的用例,您可以执行类似的操作,在这种情况下,React不会发出任何关键警告:
var image_urls = [
'http://rnplay.org/IMG_0599.jpg',
'http://rnplay.org/IMG_0602.jpg',
'http://rnplay.org/IMG_0620.jpg'
];
{/* #1 */}
<View>
<Image style={[styles.image, this.calculatedSize()]} source={{uri: image_urls[0]}} />
<Image style={[styles.image, this.calculatedSize()]} source={{uri: image_urls[1]}} />
<Image style={[styles.image, this.calculatedSize()]} source={{uri: image_urls[2]}} />
<Image style={[styles.image, this.calculatedSize()]} source={{uri: image_urls[0]}} />
</View>
{/* ... */
{/* #n */}
<View>
<Image style={[styles.image, this.calculatedSize()]} source={{uri: image_urls[0]}} />
<Image style={[styles.image, this.calculatedSize()]} source={{uri: image_urls[1]}} />
<Image style={[styles.image, this.calculatedSize()]} source={{uri: image_urls[2]}} />
<Image style={[styles.image, this.calculatedSize()]} source={{uri: image_urls[0]}} />
</View>
Run Code Online (Sandbox Code Playgroud)
显然,这将是一种可怕的方式,因此使用数组.但是React并没有将这种数组的使用(与其等效的脚本)区别开来(其中元素的长度和顺序是动态的)并且抱怨关键.您可以忽略该警告,但只需指定元素的索引值即可轻松实现静音.
简化示例.这些变化产生相同的输出,但不同之处在于字面上声明或编写脚本并发出关键警告.
var container = document.getElementById('container');
var items = ["A", "B", "C"];
var groups = Array(2).fill(items);
function render (element) {
ReactDOM.render(
element,
container
);
}
console.log("literal, no key warning");
var element = <div>
<div class="items">
<div>{items[0]}</div>
<div>{items[1]}</div>
<div>{items[2]}</div>
</div>
<div class="items">
<div>{items[0]}</div>
<div>{items[1]}</div>
<div>{items[2]}</div>
</div>
</div>;
render(element);
console.log("scripted, no key warning");
var element = <div>
{groups.map((items, i) =>
<div class="items" key={i}>
{items.map((item, j) =>
<div key={j}>{item}</div>
)}
</div>
)}
</div>;
render(element);
console.log("scripted, with key warning");
var element = <div>
{groups.map((items, i) =>
<div class="items">
{items.map(item =>
<div>{item}</div>
)}
</div>
)}
</div>;
render(element);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5574 次 |
| 最近记录: |