在React中将方法从一个组件移动到另一个组件,并且仍然可以在原始组件中使用

时间:2016-05-02 21:29:06

标签: javascript reactjs ecmascript-6

我正在使用React和ES6创建一个小型联系人应用程序。我在组件的渲染功能中显示了一些数据 - 请参阅以下问题的链接以了解原始结构......

How to specify a key for React children when mapping over an array

但是,因为我还在同一页面上放置一个表单而我需要在状态下更新我的数据,所以我不得不将数据移动到更高级别的组件。

现在我无法遍历组件,因此我的原始联系人列表显示在左侧。我不得不删除联系人列表组件中我的渲染函数中的大部分内容,因为它完全破坏了构建。

首先,这是带有表单的地址簿组件 - 这是有效的,既可以从状态中提取我最初的3个联系人,然后将新的联系人从表单连接到数组。 (这里仍需要清理代码才能使UI工作正常......)

import React from 'react';
import ContactList from './contact-list.jsx';
import ContactForm from './contact-form.jsx';
import ShortContact from './short-contact.jsx';

class AddressBook extends React.Component {

constructor() {
    "use strict";
    super();

    this.state = {
        showContacts: true,
        contacts: [
    {
        id: 1,
        fName: "aaa",
        lName: "aaaaa",
        imgUrl: "http://brainstorminonline.com/wp-content/uploads/2011/12/blah.jpg",
        email: "aaa@aaaa.com",
        phone: "999999999999"
    },
    {
        id: 2,
        fName: "bbbbb",
        lName: "bbbbbbb",
        imgUrl: "https://media.licdn.com/mpr/mpr/shrinknp_200_200/bbb.jpg",
        email: "bbb@bbb-bbb.com",
        phone: "888888888888"
    },
    {
        id: 3,
        fName: "Number",
        lName: "Three",
        imgUrl: "http://3.bp.blogspot.com/-iYgp2G1mD4o/TssPyGjJ4bI/AAAAAAAAGl0/UoweTTF1-3U/s1600/Number+3+Coloring+Pages+14.gif",
        email: "three@ccccc.com",
        phone: "333-333-3333"
    }
];
    };

}




render() {
    "use strict";
    return (
        <div className="row address-book">

            <div className="col-md-6">
                <ContactList  />
            </div>
            <div className="col-md-6">

                <button className='btn' id="contact-submit-button" type="submit" value="Create Contact">Create New Contact </button>



                <div>
                    <ContactForm  addContact={this._addContact.bind(this)}/>
                </div>
            </div>
        </div>

    );

}

_addContact (fName, lName, company, email, phone, imgURL) {
    "use strict";
    const contact = {
        id: this.state.contacts.length + 1,
        fName,
        lName,
        company,
        email,
        phone,
        imgURL
    };
    this.setState({ contacts: this.state.contacts.concat([contact]) });
}

_getContacts() {
    "use strict";
    return contactList.map((contact) => {
        "use strict";
        return (
            <ShortContact contact={contact} key={contact.id}/>)
    });
}

_getContactsTitle (contactCount) {
    "use strict";
    if(contactCount === 0) {
        return 'No Contacts';
    } else if (contactCount === 1) {
        return '1 contact';
    } else {
        return `${contactCount} contacts`;
    }
}

}

export default AddressBook;

但是,底层的2个方法_getContacts和_getContactsTitle是我的ContactForm组件中需要的方法 - 就是这个:

import React from 'react';
import ShortContact from './short-contact.jsx';




class ContactList extends React.Component {



render() {

    const contacts  = this._getContacts();


    return (
        <div>
            <h3>List of Contacts</h3>
            <h4 className="contact-count">{this._getContactsTitle((contacts.length))}</h4>
            <ul className="contact-list">
                {contacts}
            </ul>
        </div>
    );
    }
}

export default ContactList;

定义联系人的const以及通过<h4>的{​​{1}}是打破应用程序的因素,因为你可以看到它引用了来自其他组件的_getContactTitle方法以及{contacts}在_getContacts方法中。

我猜我需要做一些事情,比如将它们包装成函数并传递它们 - 但是我已经转过身来,并且不能完全看到这对React如何起作用。欢迎任何帮助。谢谢!

1 个答案:

答案 0 :(得分:1)

您需要通过道具传递联系人,而不是尝试在父级中构建联系人列表以传递下来。我的意思是这个。

ADDRESS BOOK

render() {
    "use strict";
    let contacts  = this._getContacts();
-----------^---------------^----------- get the list in the parent
    return (
        <div className="row address-book">
            <div className="col-md-6">
                <ContactList contacts={contacts} />
-------------------------------^-----------^---- important part here
            </div>
            <div className="col-md-6">
                <button className='btn' id="contact-submit-button" type="submit" value="Create Contact">Create New Contact </button>
                <div>
                    <ContactForm  addContact={this._addContact.bind(this)}/>
                </div>
            </div>
        </div>

    );
}

然后在你的CONTACT LIST组件中,只需使用列表作为道具。

render() {
    let {contacts} = this.props;
------------^--------------^---- its in the props now
    let title = contacts.length > 1 ? `${contacts.length} contacts` : contacts.length === 1 ? '1 contact' : 'No Contacts';
    return (
        <div>
            <h3>List of Contacts</h3>
            <h4 className="contact-count">{title}</h4>
            <ul className="contact-list">
                {contacts}
            </ul>
        </div>
    );
    }
}

从这里你可以删除contactTitle函数。让孩子渲染,因为它知道数组的长度(因为它在道具中)。

作为旁注,在_addContact函数中。而不是创建一个新的数组并将其与状态接触数组连接,只需将新数组推入当前状态即可。它更好的存储(即不需要创建一个新的数组来将新项目组合到数组中)。

this.setState({ contacts: this.state.contacts.push(contact) });