【问题标题】:React - Each child in an array or iterator should have a unique "key" propReact - 数组或迭代器中的每个孩子都应该有一个唯一的“关键”道具
【发布时间】: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>
);

【问题讨论】:

  • 可能是一个愚蠢的问题,但是:你记得导入你的组件吗?当我在组件中包含 时,我得到了同样的消息,其中 MyComponent 没有被导入..
  • 我已经编辑了你的问题。将来有反应问题时,还请包括javascript 标签:由于某种原因,如果您不这样做,SO 的语法突出显示将不起作用。 3 年前有人问过关于 meta 的问题,但显然它因缺乏关注而死。

标签: javascript reactjs


【解决方案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 组件的孩子。 >>&lt;App&gt;{//the children you are passing here}&lt;/App&gt;。这是可以传递数组的地方。请参阅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 的反馈。如果您认为我仍然缺少任何内容,请纠正我。
猜你喜欢
  • 2018-02-08
  • 1970-01-01
  • 2018-08-31
  • 2017-02-23
  • 2017-02-03
  • 2018-05-22
  • 2018-04-29
  • 1970-01-01
相关资源
最近更新 更多