#reactjs
#reactjs
Вопрос:
Да, поэтому я пытаюсь изучить react и делаю простой проект, чтобы лучше его понять.
в основном то, что я пытаюсь сделать, это использовать useState из одного файла и позволить ему быть измененным функцией onClick в другом файле следующим образом:
list.js
export const List= [
{id:1, obj:'item1'},
{id:2, obj:'item2'},
{id:3, obj:'item3'},
{id:4, obj:'item4'},] ;
index.js
import React,{useState} from 'react'
import {List} from './list'
import ItemList from './ItemList'
function Items(){
const [items,setItems] = React.useState(List);
return (
<>
<h1>{items.length} Items in total</h1>
{items.map((itemArr)=>{
return (
<ItemList {...itemArr}/>
)
})}
</>
)
}
ReactDom.render(<Items />,document.getElementById('root')
)
ItemList.js
import React from 'react'
function ItemList(props) {
const {id,obj} = props;
const removeItem = (id) =>{
//Code Here
}
return (
<div>
<h3>{id}</h3>
<h4>{obj}</h4>
<button onClick={()=> removeItem(id)}>Remove</button>
</div>
)
}
export default ItemList
Что я хочу сделать, так это то, что когда я нажимаю кнопку, removeItem
функция удалит любой элемент с id
помощью and use .filter
. Но проблема, с которой я сталкиваюсь, заключается в том, что я не могу понять, как я могу вызвать и вернуть что-то setItems
, чтобы я мог изменить значение. И я не могу найти способ перейти setItem
к itemList.js
.
Ответ №1:
Вы можете передать setItems
в качестве поддержки ItemList
function Items(){
const [items,setItems] = React.useState(List);
return (
<>
<h1>{items.length} Items in total</h1>
{items.map((itemArr) => {
return (
<ItemList {...itemArr} setItems={setItems} /> // <-- pass callback
)
})}
</>
)
}
И использование реквизитов в дочернем элементе. Используйте обновление функционального состояния для доступа к предыдущему состоянию, фильтрации его и возврата следующего состояния.
function ItemList(props) {
const { id, obj, setItems } = props; // <-- destructure from props
const removeItem = (id) =>{
setItems(items => items.filter(item => item.id !== id)) // <-- update state
}
return (
<div>
<h3>{id}</h3>
<h4>{obj}</h4>
<button onClick={() => removeItem(id)}>Remove</button>
</div>
)
}
Как правило, хотя предпочтительнее, чтобы компонент, владеющий состоянием, также поддерживал все функции, которые работают с этим состоянием. Другими словами, вы должны определить removeHandler
в родительском элементе и передать ссылку на него. Это позволяет родительскому компоненту поддерживать инвариант состояния, а не ответственность любого дочернего компонента.
function Items(){
const [items,setItems] = React.useState(List);
const removeItem = (id) =>{
setItems(items => items.filter(item => item.id !== id))
}
return (
<>
<h1>{items.length} Items in total</h1>
{items.map((itemArr) => {
return (
<ItemList {...itemArr} removeItem={removeItem} />
)
})}
</>
)
}
function ItemList(props) {
const { id, obj, removeItem } = props;
return (
<div>
<h3>{id}</h3>
<h4>{obj}</h4>
<button onClick={() => removeItem(id)}>Remove</button>
</div>
)
}
Ответ №2:
Вам нужно передать функцию обратного вызова от Items
компонента к ItemList
компоненту.
index.js
import React,{useState} from 'react'
import {List} from './list'
import ItemList from './ItemList'
function Items(){
const [items,setItems] = React.useState(List);
onClickHandler(id){
....
change state
....
}
return (
<>
<h1>{items.length} Items in total</h1>
{items.map((itemArr)=>{
return (
<ItemList onClickHandler={onClickHandler} {...itemArr}/>
)
})}
</>
)
}
ReactDom.render(<Items />,document.getElementById('root')
)
ItemList.js
import React from 'react'
function ItemList(props) {
const {id,obj,onClickHandler} = props;
return (
<div>
<h3>{id}</h3>
<h4>{obj}</h4>
<button onClick={()=> onClickHandler(id)}>Remove</button>
</div>
)
}
export default ItemList
В React данные могут передаваться только в одном направлении, поэтому для обновления данных в родительском компоненте из дочернего компонента вам необходимо передать функции в качестве реквизита