我有一个将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子组件上?
预先感谢一百万。
答案 0 :(得分:0)
一个解决方案可能是在App中创建removeCard方法,如果您要控制addNewCard的click事件没有发生,则将触发该方法。
// App.js
...
const removeCard = username => {
console.log("Tried to remove card ....", username)
setCards([...cards.filter(card => card.name != username)])
}
然后将removeCard和addNewCard都传递给CardList。
// App.js
...
<CardsList remove={removeCard} cards={cards} add={addNewCard}/>
继续并将这些方法传递给CardsList中的Card。您还需要分配给布尔值的卡片上的一些道具,例如“ selected”。
// CardsList.js
return (
<div>
{props.cards.map(card => (
<Card key={card.html_url} {... card}
remove={handleClick}
add={props.add}
selected={false}
/>
))}
</div>
在子Card组件中设置钩子和click事件,
// 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的控制从窗体转移到Card,但是最终迫使UI遵循Card组件的状态。