我对Hooks来说还很陌生,我正在尝试制作一本小型通讯录。
所以我有两个组成部分:
我希望在单击 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}>
✕
</span>
<br />
<span className='contact-firstname'>{props.firstname}</span>
<hr className='separator' />
<span className='contact-notes'>{props.notes}</span>
</div>
)
}
export default ContactCard
答案 0 :(得分:1)
这里确实有一些选择,最简单的方法可能只是传递“ 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)}>
✕
</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
钩子的一个示例,不确定它有多好
答案 1 :(得分:0)
从您的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)}>
✕
</span>
<br />
<span className='contact-firstname'>{props.firstname}</span>
<hr className='separator' />
<span className='contact-notes'>{props.notes}</span>
</div>
)
}
export default ContactCard
我还没有尝试过代码,但是我认为您应该沿着这条路前进。