簡體   English   中英

React Map function 不會在每次更新 state 數組時重新渲染組件

[英]React Map function is not re-rendering the component every time the state array gets updated

我正在嘗試使用材料 UI select 字段以及用於學習的 Formik 的 withFormik 創建待辦事項應用程序。 添加功能有效,但每次我嘗試刪除一個項目時,要么刪除整個列表,要么刪除最后一個元素,無論我單擊刪除的是哪個項目。

表單組件

`

import React from 'react'
import { withFormik } from 'formik';
import { FormControl , Select, InputLabel, MenuItem, Fab, 
  // Button
} from '@mui/material'
import AddIcon from '@mui/icons-material/Add'
import { useState } from 'react';
import List from './List'



const Form = (props) => {
    

const[items, setItems]= useState([]);

// const handleChange = (e)=>{
//   setCountry(e.target.value);
// }
const{
  values,
  handleChange,
  handleSubmit
}= props;


const handleClick = ()=>{
    // setItems((allitem)=>{   
    //   return[...allitem, values.name];
    //   // items.push(values.name)       
    // }
      
    // );
    items.push(values.name)
    setItems(items => [...items])
    

      console.log(items);
  }

const deleteItem = (id)=>{
  console.log(values.name, id);
  // setItems((allItems)=>{
  //   return allItems.splice(id, 1)
  //   })
  
  setItems(()=>{
   return items.splice(id, 1)
  })


// setItems(()=>{
//   return items.filter((elem, index)=>{
//     return index!==id;
//   })
// })

    console.log(items)

}

  return (
    <div className='main'>
    <FormControl sx={{ m: 1, minWidth: 250 }} size="small" onSubmit={handleSubmit}>
  <InputLabel id="country-label">Country</InputLabel>
  <Select
    labelId="Country-label-id"
    id="countries"
    value={values.name}
    label="Country"
    name= "name"
    onChange={handleChange}
  >
    <MenuItem value={9}></MenuItem>
    <MenuItem value={10}>India</MenuItem>
    <MenuItem value={20}>Canada</MenuItem>
    <MenuItem value={30}>Albania</MenuItem>
    <MenuItem value={40}>Zambia</MenuItem>
    <MenuItem value={50}>USA</MenuItem>
    <MenuItem value={60}>Poland</MenuItem>
  </Select>
 
</FormControl>
       <Fab size='small' color="primary" aria-label="add" id='button'>
  <AddIcon onClick={handleClick}/>
</Fab>






<ul>
{/* {console.log(items)} */}
      {items.map((itemval, index)=>{
        
        return (
          <List 
          key= {index}
          id={index}
          valCountry={itemval}
          onDel= {deleteItem}
            
          /> 
        );

      })}
      {/* <Button variant='contained' size='medium' id='clear-btn' onClick={()=>{setItems([])}}>Clear All</Button> */}
    </ul>

    

    </div>
   
  );
  }

  const MySelectField = withFormik({
    mapPropsToValues: ()=>({name: ''}),
    enableReinitialize: true,

    handleSubmit: (values, { setSubmitting }) => {
      setTimeout(() => {
        console.log(JSON.stringify(values, null, 2));
        setSubmitting(false);
      }, 1000);
    },

  })(Form)

export default MySelectField;

`

在我的表單組件中,我使用了 withFormik 和 Material UI。 我已經評論了我的一些邏輯。 他們都沒有工作。

列表組件

`

import React, { useState } from 'react'
// import { withFormik } from 'formik';
import {Select,MenuItem,} from '@mui/material'
import DeleteIcon from '@mui/icons-material/Delete';

const List = (props) => {
const[listVal, setListVal]= useState(props.valCountry);
//  const{
//   values,
//   handleChange
//  }=props

  return (
    <>
   
        <li> {
            <Select
    labelId="Country-label-id"
    id="countries"
    value={listVal}
    label="Country"
    name='listvalue'
    onChange={(e)=> setListVal(e.target.value)}
  >
    <MenuItem value={9}></MenuItem>
    <MenuItem value={10}>India</MenuItem>
    <MenuItem value={20}>Canada</MenuItem>
    <MenuItem value={30}>Albania</MenuItem>
    <MenuItem value={40}>Zambia</MenuItem>
    <MenuItem value={50}>USA</MenuItem>
    <MenuItem value={60}>Poland</MenuItem>
  </Select>
        } 
        <DeleteIcon margin-top='5px' fontSize='large' onClick={()=>{
              props.onDel(props.id);
        }}

        />
         </li>
       
       
    </>
  )
}



export default List;

` 這是我使用 Map function 在我的表單組件中傳遞的列表組件,但不知何故它不起作用。

以前我使用過簡單的反應鈎子並且它工作得很好但是當我在代碼中集成 withFormik() 時刪除功能不起作用。

在此處輸入圖像描述

首先,我們需要修復您的handleClickdeleteItem 永遠不要改變 state,你只能用setItems function 改變 state。正如@terpinmd 指出的那樣,拼接改變了 state,這是不好的。

這就是我編寫函數的方式

const handleClick = () => {
  // You should only mutate the state with setItems
  // If you need the previous state, use the function form of setItems
  // Dont use the same name for the state and the function, this might cause problems
  setItems((currentItems) => [values.name, ...currentItems]);
};

const deleteItem = (index) => {
  // If you only use the index, dont lie and say you use an id, this just becomes confusing
  setItems((currentItems) => currentItems.filter((_, i) => i !== index));
};

開始調整您的代碼,如果您還有其他問題,請更新您的問題。

編輯:您面臨的第二個問題可能是由於您使用索引作為鍵造成的。 https://reactjs.org/docs/lists-and-keys.html

由於項目有自己的 state,因此它們將保留 state。您可以通過從List組件中向上移動 state 來解決此問題,最好將值存儲在items中,因為您現在只有初始值。 從那時起,您將始終向下饋送值,以便項目可以調整到正確的值。

或者確保一個項目的鍵不會改變。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM