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>
);

【问题讨论】:

可能是一个愚蠢的问题,但是:你记得导入你的组件吗?当我在组件中包含 时,我得到了同样的消息,其中 MyComponent 没有被导入.. 这可以帮助你***.com/questions/28329382/… 我已经编辑了你的问题。将来有反应问题时,还请包括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 组件的孩子。 >>&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 的反馈。如果您认为我仍然缺少任何内容,请纠正我。

以上是关于React - 数组或迭代器中的每个孩子都应该有一个唯一的“关键”道具的主要内容,如果未能解决你的问题,请参考以下文章

数组或迭代器中的每个孩子都应该有一个唯一的“key”道具。检查 `Abstractfactory` 的渲染方法

警告:数组或迭代器中的每个孩子都应该有一个唯一的“key”道具。检查“搜索”的渲染方法

警告:数组或迭代器中的每个孩子都应该有一个唯一的“key”道具。检查`Units`的渲染方法

警告:数组或迭代器中的每个孩子都应该有一个唯一的“key”道具。检查`MovieResults`的渲染方法

在复杂的 React 组件中查找重复键

Ionic + React.js:警告:列表中的每个孩子都应该有一个唯一的“关键”道具