我有一个应用程序将GitHub用户添加到列表中。当我在表单中输入输入时,将返回一个用户并将其添加到列表中。我希望只有在资源请求后显示用户时单击用户才能将用户添加到列表中。具体来说,我想要的是在子组件中有一个click事件触发根组件触发钩子,将新元素添加到列表中。
根组件,
const App = () => {
const [cards, setCards] = useState([])
const addNewCard = cardInfo => {
console.log("addNewCard called ...")
setCards([cardInfo, ...cards])
}
return (
<div className="App">
<Form onSubmit={addNewCard}/>
<CardsList cards={cards} />
</div>
)
}
export default App;
表单组件,
const Form = props => {
const [username, setUsername] = useState('');
const chooseUser = (event) => {
setUsername(event.target.value)
}
const handleSubmit = event => {
event.persist();
console.log("FETCHING ...")
fetch(`http://localhost:3666/api/users/${username}`, {
})
.then(checkStatus)
.then(data => data.json())
.then(resp => {
console.log("RESULT: ", resp)
props.onSubmit(resp)
setUsername('')
})
.catch(err => console.log(err))
}
const checkStatus = response => {
console.log(response.status)
const status = response.status
if (status >= 200 && status <= 399) return response
else console.log("No results ...")
}
return (
<form onSubmit={handleSubmit}>
<input
type="text"
placeholder="Gitbub username"
value={username}
required
onChange={chooseUser}
onKeyUp={debounce(handleSubmit, 1000)}
/>
<button type="submit">Add card</button>
</form>
)
}
export default Form;
列表组件,
const CardsList = props => {
return (
<div>
{props.cards.map(card => (
<Card key={card.html_url} {... card}
/>
))}
</div>
)
}
export default CardsList
和卡组件,
const Card = props => {
const [selected, selectCard] = useState(false)
return (
<div style={{margin: '1em'}}>
<img alt="avatar" src={props.avatar_url} style={{width: '70px'}} />
<div>
<div style={{fontWeight: 'bold'}}><a href={props.html_url}>{props.name}</a></div>
<div>{props.blog}</div>
</div>
</div>
)
}
export default Card
现在,我的Form组件具有所有控件。如何将App中的addNewCard方法控制到Card子组件?
提前一百万谢谢。
一种解决方案可能是在App中创建一个removeCard方法,如果您想要控制addNewCard的click事件没有发生,则会触发该方法。
// App.js
...
const removeCard = username => {
console.log("Tried to remove card ....", username)
setCards([...cards.filter(card => card.name != username)])
}
然后你通过两个删除卡并将卡添加到卡列表。
// App.js
...
<CardsList remove={removeCard} cards={cards} add={addNewCard}/>
继续将这些方法传递给CardList中的Card。您还需要将卡上的一些道具分配给布尔值,例如“已选择”。
// CardsList.js
return (
<div>
{props.cards.map(card => (
<Card key={card.html_url} {... card}
remove={handleClick}
add={props.add}
selected={false}
/>
))}
</div>
在子卡组件中设置钩子和单击事件,
// Card.js
...
const [selected, selectCard] = useState(false)
...
并配置您的事件以触发挂钩并使用状态。
// Card.js
...
return (
<div style={{margin: '1em', opacity: selected ? '1' : '0.5'}}
onMouseLeave={() => selected ? null : props.remove(props.name)}
onClick={() => selectCard(true)}
>
...
这并没有真正将addNewCard的控制从Form转移到Card,但它最终迫使UI遵循Card组件的状态。