I have a problem with the key props in a React JS component.
I'm getting
Warning: Each child in an array or iterator should have a unique "key" prop. Check the render method of Login. It was passed a child from App.
warning in console log. App component is as follows :
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;
And my login component is as follows :
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;
I'm still new in React and I'm not sure what should I pass like a key and where?
UPDATE
LoginForm component :
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;
Routes file :
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;
HomePage Component
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>
);
I don't know how your LoginForm
component looks like.
But each time you iterate over an array you have to set the key
prop to each of the resulting DOM
element as React
needs it to optimize the re-rendering.
For example:
<div className="container">
{myarray.map((element, index) => {
return <div key={'mykey' + index}>{element}</div>;
})}
</div>
React
for example will detect duplicates and only renders the first node
with this key
.
The reason behind this warning is that you have not passed 'key' property. React uses this property for optimizing the rendering process as in when something changes in React, a re-render will occur only for what all has changed.
If our children are dynamic and in case they get shuffled with random functions or new components are introduced in the beginning of an array, the re-render is likely to get messed up. So, assigning this 'key' property helps us make sure that the state and identity of our components is maintained through multiple renders. Please find below a sample code snippet demonstrating how to pass a key.
<MyComponent key={{item.key}}/>
The importance of key is beautifully explained here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With