передача и возврат useState в react

#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 данные могут передаваться только в одном направлении, поэтому для обновления данных в родительском компоненте из дочернего компонента вам необходимо передать функции в качестве реквизита