繁体   English   中英

使用钩子从父组件进行状态管理

[英]State management from parent component using hooks

我对 Hooks 很陌生,我正在尝试构建一个小型地址簿。

所以我有两个组成部分:

  • ContactCard 组件
  • ContactsList 组件

我希望在单击X时移除卡片。 我设法切换了我的联系人的已删除道具,但我不知道如何强制重新呈现ContactsList

 import React, { useState } from 'react' import ContactsList from './components/contacts-list/contacts-list.component' import './App.scss' function App() { const [contacts] = useState([ { key: 0, name: 'Lennon', firstname: 'John', notes: 'smart guy', deleted: false }, { key: 1, name: 'Starr', firstname: 'Ringo', notes: 'funny guy', deleted: false } ]) return ( <div className='App'> <ContactsList contacts={contacts} /> </div> ) } export default App

 import React, { useState, useEffect } from 'react' import ContactCard from '../contact-card/contact-card.component' import './contacts-list.styles.scss' function ContactsList(props) { const [contacts, setContacts] = useState(props.contacts) return ( <div className='contacts-list'> <span className='title'>Contacts</span> {contacts .filter(contact => contact.deleted === false) .map(contact => ( <ContactCard name={contact.name} firstname={contact.firstname} notes={contact.notes} deleted={contact.deleted} /> ))} <hr /> </div> ) } export default ContactsList

 import React, { useState } from 'react' import './contact-card.styles.scss' function ContactCard(props) { const [contact, setContact] = useState([ { name: props.name, firstname: props.firstname, notes: props.notes, deleted: false } ]) function deleteContact() { const currentContact = [...contact] currentContact[0].deleted = true setContact(currentContact) } return ( <div className='contact-card'> <span className='contact-name'>{props.name}</span> <span className='delete-contact' onClick={deleteContact}> &#10005; </span> <br /> <span className='contact-firstname'>{props.firstname}</span> <hr className='separator' /> <span className='contact-notes'>{props.notes}</span> </div> ) } export default ContactCard

这里真的有几个选项,最简单的可能只是传递一个“onContactDeleted”道具并回调给父母,让他们知道更新状态。 这种方法并不总是最干净的,尤其是对于高度嵌套的组件,但我会推荐它作为开始,因为它确实是帮助您了解 prop 和 state 更改如何工作的最普通的方法。 请注意,我保留了您的软删除方法,但您也可以将其从列表中删除。

卡片

import React, { useState } from 'react'

import './contact-card.styles.scss'

function ContactCard(props) {

  function deleteContact(key) {
    props.onContactDeleted(key)
  }

  return (
    <div className='contact-card'>
      <span className='contact-name'>{props.name}</span>
      <span className='delete-contact' onClick={() => deleteContact(props.contactKey)}>
        &#10005;
      </span>
      <br />
      <span className='contact-firstname'>{props.firstname}</span>
      <hr className='separator' />
      <span className='contact-notes'>{props.notes}</span>
    </div>
  )
}

export default ContactCard

列表

import React, { useState, useEffect } from 'react'
import ContactCard from '../contact-card/contact-card.component'

import './contacts-list.styles.scss'

function ContactsList(props) {
  const [contacts, setContacts] = useState(props.contacts)

  return (
    <div className='contacts-list'>
      <span className='title'>Contacts</span>
      {contacts
        .filter(contact => contact.deleted === false)
        .map(contact => (
          <ContactCard
            contactKey={contact.key}
            name={contact.name}
            firstname={contact.firstname}
            notes={contact.notes}
            deleted={contact.deleted}
            onContactDeleted={props.onContactDeleted}
          />
        ))}
      <hr />
    </div>
  )
}

export default ContactsList

应用程序

import ContactsList from './components/contacts-list/contacts-list.component'
import './App.scss'

function App() {
  const [contacts, setContacts] = useState([
    {
      key: 0,
      name: 'Lennon',
      firstname: 'John',
      notes: 'smart guy',
      deleted: false
    },
    {
      key: 1,
      name: 'Starr',
      firstname: 'Ringo',
      notes: 'funny guy',
      deleted: false
    }
  ])
  return (
    <div className='App'>
      <ContactsList contacts={contacts} 
                    onContactDeleted={
                      (key_to_delete) => {
                         //note this might not be correct, use it as pseudocode
                         var copy = [...contacts]
                         var contact = copy.find(x => x.key == key_to_delete)
                         if(contact)
                         {
                            contact.deleted = true;
                            setContacts(copy)
                         }
                      }
                     }/>
    </div>
  )
}

export default App

一旦你有了它,你就可以使用诸如 redux 或useContext钩子之类的东西来共享状态并“切断中间人”

这是我在网上很快找到的useContext hook的一个例子,不知道它有多好

https://www.codementor.io/@sambhavgore/an-example-use-context-and-hooks-to-share-state-between-different-components-sgop6lnrd

从你的App开始,我建议你将你的联系人对象移动到一个常量,因为在这个级别不需要useState

// constants.js
export const contacts = [
    {
      key: 0,
      name: 'Lennon',
      firstname: 'John',
      notes: 'smart guy'
    },
    {
      key: 1,
      name: 'Starr',
      firstname: 'Ringo',
      notes: 'funny guy'
    }
  ]
};

// App.js
import React from 'react';
import { contacts } from './constants';
import ContactsList from './components/contacts-list/contacts-list.component'
import './App.scss'

function App() {
  return (
    <div className='App'>
      <ContactsList contacts={contacts} />
    </div>
  )
}

export default App

继续ContactList组件,因为它是呈现每个联系人的组件,我将在此处构建我的状态。 因此,我会知道是否需要事先提供联系人。

import React, { useState } from 'react'
import ContactCard from '../contact-card/contact-card.component'

import './contacts-list.styles.scss'

function ContactsList(props) {
  const [contacts, setContacts] = useState(props.contacts);
  const handleDeletion = id => {
    setContacts(contacts.filter(contact => contact.id !== id));
  }

  return (
    <div className='contacts-list'>
      <span className='title'>Contacts</span>
      {contacts.length ? 
        contacts.map(contact => 
          <ContactCard
            id={contact.id}
            name={contact.name}
            firstname={contact.firstname}
            notes={contact.notes}
            handleDeletion={handleDeletion}
          />
        ) : null}
      <hr />
    </div>
  )
}

export default ContactsList

请注意,我正在将处理删除的函数传递给我的 ContactCard,而我仍然在这里决定是否应该显示我的联系人。

import React from 'react'

import './contact-card.styles.scss'

function ContactCard(props) {
  return (
    <div className='contact-card'>
      <span className='contact-name'>{props.name}</span>
      <span className='delete-contact' onClick={() => props.handleDeletion(props.id)}>
        &#10005;
      </span>
      <br />
      <span className='contact-firstname'>{props.firstname}</span>
      <hr className='separator' />
      <span className='contact-notes'>{props.notes}</span>
    </div>
  )
}

export default ContactCard

我没有试过代码,但我认为你应该走这条路。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM