React - 数组或迭代器中的每个孩子都应该有一个唯一的“关键”道具
Posted
技术标签:
【中文标题】React - 数组或迭代器中的每个孩子都应该有一个唯一的“关键”道具【英文标题】:React - Each child in an array or iterator should have a unique "key" prop 【发布时间】:2016-10-05 17:17:54 【问题描述】:我对 React JS 组件中的 key props 有疑问。
我来了
警告:数组或迭代器中的每个孩子都应该有一个唯一的“key”道具。检查登录的渲染方法。它是从 App 传递的一个孩子。
控制台日志中的警告。应用组件如下:
import React from 'react';
import Header from '../common/header';
import HeaderCompact from '../common/headerCompact';
import Footer from '../common/footer';
class App extends React.Component
constructor(props)
super(props);
this.state =
lang: 1
;
changeLang(name, event)
event.preventDefault();
switch (name)
case "fra" :
this.setState(lang: 2);
break;
case "ger" :
this.setState(lang: 3);
break;
case "ned" :
this.setState(lang: 4);
break;
default:
this.setState(lang: 1);
render()
let currentRoute = this.props.location.pathname.slice(1);
let header = currentRoute === "" ? <Header onClick=this.changeLang lang=this.state.lang/> :
<HeaderCompact currentRoute=currentRoute onClick=this.changeLang lang=this.state.lang/>;
return (
<div>
header
React.cloneElement(this.props.children, lang: this.state.lang)
<Footer lang=this.state.lang/>
</div>
);
export default App;
我的登录组件如下:
import React from 'react';
import LoginForm from './loginForm';
const Login = (currentLanguage) =>
const language = currentLanguage;
return (
<div className="container">
<div className="row">
<p className="col-lg-4 col-xs-12 col-md-4 loginTitle noPadding">language.loginTitle</p>
<div className="col-lg-8 col-xs-12 col-md-8 loginForm noPadding">
<LoginForm currentLanguage=language/>
</div>
</div>
</div>
);
;
export default Login;
我还是 React 的新手,我不确定我应该传递什么,比如一个键,传递到哪里?
更新
LoginForm 组件:
import React from 'react';
import Link from 'react-router';
import TextInput from '../../common/formElements/textInput';
import LoginButton from '../../common/formElements/button';
class LoginForm extends React.Component
constructor(props, context)
super(props, context);
this.state =
loginData:
username: '',
password: ''
,
errors:
;
this.buttonClickHandle = this.buttonClickHandle.bind(this);
this.loginHandle = this.loginHandle.bind(this);
loginHandle(event)
let field = event.target.name;
let value = event.target.value;
this.state.loginData[field] = value;
return this.setState(loginData: this.state.loginData);
buttonClickHandle(event)
event.preventDefault();
alert("It's clicked/n");
render()
const language = this.props.currentLanguage;
return (
<div className="contact_form">
<form role="form" action="" method="post" id="contact_form">
<div className="col-lg-4 col-md-4 col-sm-4 col-xs-12 smScrPdLeft" style=marginTop: 5>
<TextInput
type="text"
name="username"
label=""
placeholder=language.loginUsername
className="templateInput loginUsername col-lg-12 col-md-12 col-sm-12 col-xs-12"
id="name"
sizeClass=""
onChange=this.loginHandle
value=this.state.username
errors=this.state.errors.username
/>
</div>
<div className="col-lg-4 col-md-4 col-sm-4 col-xs-12 smPadding" style=marginTop: 5>
<TextInput
type="password"
name="password"
label=""
placeholder=language.loginPassword
className="templateInput loginPassword col-lg-12 col-md-12 col-sm-12 col-xs-12"
id="password"
sizeClass=""
onChange=this.loginHandle
value=this.state.password
errors=this.state.errors.password
/>
<Link to="/" className="forgotPassLabel">language.forgotPassword</Link>
</div>
<div className="col-lg-4 col-md-4 col-sm-4 col-xs-12 btnLogin noPadding smScrPdRight" style=marginTop: 4>
<LoginButton onClick=() => this.buttonClickHandle(event) name="registration" value=language.loginBtnText className="rightFloat" icon="user"/>
</div>
</form>
</div>
);
export default LoginForm;
路线文件:
import React from 'react';
import IndexRoute, Route from 'react-router';
import App from './components/App';
import HomePage from './components/HomePage';
const routes = (
<Route path="/" component=App>
<IndexRoute component=HomePage/>
</Route>
);
export default routes;
主页组件
return (
<div>
<div className="sidebar-menu-container" id="sidebar-menu-container">
<div className="sidebar-menu-push">
<div className="sidebar-menu-overlay"></div>
<div className="sidebar-menu-inner">
<section className="marginOnXs" style=width: '100%', padding: 0>
<div className="container">
<div className="row hideOnXS">
<MainSlider />
</div>
</div>
</section>
<div id="cta-1" className="onlyOnDesktop">
<Login currentLanguage=languageHome/>
</div>
<section className="why-us" style=paddingTop: 0>
<Info currentLanguage=languageHome/>
</section>
<div className="clearfix"></div>
<section className="featured-listing">
<CarsList allCars=carsList() currentLanguage=languageHome/>
</section>
<section className="contactSection">
<ContactForm currentLanguage=languageHome/>
</section>
</div>
</div>
</div>
</div>
);
【问题讨论】:
可能是一个愚蠢的问题,但是:你记得导入你的组件吗?当我在组件中包含javascript
标签:由于某种原因,如果您不这样做,SO 的语法突出显示将不起作用。 3 年前有人问过关于 meta 的问题,但显然它因缺乏关注而死。
【参考方案1】:
我不知道你的LoginForm
组件是什么样子的。
但是每次遍历数组时,都必须将 key
属性设置为每个结果 DOM
元素,因为 React
需要它来优化重新渲染。
例如:
<div className="container">
myarray.map((element, index) =>
return <div key='mykey' + index>element</div>;
)
</div>
例如,React
将检测重复项并仅使用此 key
呈现第一个 node
。
【讨论】:
我更新了我的问题。但我没有在任何地方迭代数组,我没有任何地方的地图。 嗯。this.props.children
在您的 App
组件中究竟传递了什么?也许这是一个数组?在我看来,其他一切都很好。
我更新了 App 组件的代码。状态通过;那只是一个数字。
不,我的意思是传递给App
组件的孩子。 >><App>//the children you are passing here</App>
。这是可以传递数组的地方。请参阅facebook.github.io/react/tips/children-props-type.html顶部的描述
App 组件是从路由文件中调用的,来自 React Router。我用那个文件更新了我的问题。【参考方案2】:
这个警告背后的原因是你没有传递'key'属性。 React 使用此属性来优化渲染过程,就像当 React 中的某些内容发生更改时,只会对所有更改的内容进行重新渲染。
如果我们的孩子是动态的,并且如果他们被随机函数打乱或者在数组的开头引入了新组件,那么重新渲染很可能会搞砸。因此,分配这个“键”属性有助于我们确保组件的状态和身份通过多次渲染得到维护。 请在下面找到演示如何传递密钥的示例代码 sn-p。
<MyComponent key=item.key/>
key 的重要性在here 中得到了很好的解释。
【讨论】:
虽然肯定是正确的,但通过添加代码示例可以改进这个答案。 谢谢,@JaredSmith!编辑了我的答案。 我当然感谢您更新您的答案,但请实际发布代码 in 您的答案:链接可能而且确实会失效。如果代码示例是您从其他地方获得的,而不是您自己创建的,请务必添加归因链接,但仍将代码发布在您的实际答案中。 感谢@JaredSmith 的反馈。如果您认为我仍然缺少任何内容,请纠正我。以上是关于React - 数组或迭代器中的每个孩子都应该有一个唯一的“关键”道具的主要内容,如果未能解决你的问题,请参考以下文章
数组或迭代器中的每个孩子都应该有一个唯一的“key”道具。检查 `Abstractfactory` 的渲染方法
警告:数组或迭代器中的每个孩子都应该有一个唯一的“key”道具。检查“搜索”的渲染方法
警告:数组或迭代器中的每个孩子都应该有一个唯一的“key”道具。检查`Units`的渲染方法