Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React - Each child in an array or iterator should have a unique "key" prop

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>
);
like image 942
Boky Avatar asked Jun 06 '16 07:06

Boky


2 Answers

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.

like image 161
Richard Rutsche Avatar answered Oct 26 '22 10:10

Richard Rutsche


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.

like image 24
Abhishek Maheshwari Avatar answered Oct 26 '22 11:10

Abhishek Maheshwari