Javascript 使用useEffect更新状态时出现问题

Javascript 使用useEffect更新状态时出现问题,javascript,reactjs,axios,state,use-effect,Javascript,Reactjs,Axios,State,Use Effect,我想更新我的状态(对象列表),但useEffect或deleteFunction有问题。 这是我的密码: const [itemName, setItemName] = useState({}); const [isDeleted, setIsDeleted] = useState(false); const createArray = () => { const { items } = item; const newNames = items.map(item =>

我想更新我的状态(对象列表),但useEffect或deleteFunction有问题。 这是我的密码:

const [itemName, setItemName] = useState({});
const [isDeleted, setIsDeleted] = useState(false);

const createArray = () => {
   const { items } = item;
   const newNames = items.map(item => item);
   setItemName({ ...newNames });
 };


useEffect(() => {
      getItems();
      createArray();
    }, [isDeleted]);

const onDeleteClick = id => {
  deleteItem(id);
  setIsDeleted(!isDeleted);
};

console.log(itemName);

    return(
// Contaners and other things//
    item.items.map({id, name, content}, index) =>{
    // Some other code also Form and FormGroup etc. //
    <Button
       style={{
         position: "absolute",
         left: "100%",
         marginLeft: "-2.2rem",
         marginTop: "-0.8rem"
        }}
       color="danger"
       size="md"
       onClick={onDeleteClick.bind(this, _id)}
       >&times;
     </Button>
// rest of code
并删除_项的大小写:

case DELETE_ITEM:
      return {
        ...state,
        items: state.items.filter(item => item._id !== action.payload)
      };
问题是,在第一次单击后,“itemName”没有改变,但在第二次单击后,它开始工作。例如,在开始时,我有10个对象,单击“删除”后,我应该有9个,但itemName有10个,以后的对象数比itemName对象多一个

启动时:

第一次单击时:

第二次单击时:

最后,我有0个对象,但itemName中有1个对象。 列表中的元素在视觉上应该消失,但若我删除一些元素并尝试更改其他元素的名称或内容,那个么将数据调整为正确的元素就会出现问题

下面是getItems操作:

export const getItems = () => dispatch => {
  dispatch(setItemsLoading());
  axios
    .get('/api/items')
    .then(res =>
      dispatch({
        type: GET_ITEMS,
        payload: res.data
      })
    )
    .catch(err =>
      dispatch(returnErrors(err.response.error, err.response.status))
    );
};
减速器壳体:

 case GET_ITEMS:
      return {
        ...state,
        items: action.payload,
        loading: false
      };

以下是全部内容:

import React, { useEffect, useState } from 'react';
import {
  Container, ListGroup, ListGroupItem, Button, Form,
  FormGroup,
  Label,
  Input
} from 'reactstrap';
import { CSSTransition, TransitionGroup } from 'react-transition-group';
import { connect } from 'react-redux';
import { getItems, deleteItem, updateItem } from '../actions/itemActions';
import PropTypes from 'prop-types';

const MyList = ({ getItems, deleteItem, isAuthenticated, item, updateItem }) => {

  const [itemName, setItemName] = useState({});
  const [isDeleted, setIsDeleted] = useState(false);

  const createArray = () => {
    const { items } = item;
    const newNames = items.map(item => item);
    setItemName({ ...newNames });
  };



  useEffect(() => {
    getItems();
    createArray();
  }, [isDeleted]);




  const onChangeName = (item, index) => {
    return (event) => {
      const name = event.target.value;
      setItemName(prevObjs => ({ ...prevObjs, [index]: { ...item[index], name } }));
      console.log(itemName);
    }
  }
  const onChangeContent = (item, index) => {
    return (event) => {
      const content = event.target.value;
      setItemName(prevObjs => ({ ...prevObjs, index: { ...item[index], content } }));
    }
  }

  const onDeleteClick = id => {
    deleteItem(id);
    setIsDeleted(!isDeleted);
  };

  console.log(itemName);


  return (
    <Container>
      <div className="mb-3"></div>
      <ListGroup>
        <TransitionGroup >
          {item.items.map(({ _id, name, content, date }, index) => (
            < CSSTransition key={_id} timeout={500} classNames="fade" >
              <ListGroupItem className="mb-3">
                {isAuthenticated ?
                  <div>
                    <Form onSubmit={e => {
                      e.preventDefault();
                      const { name, content } = itemName[index];
                      const newItem = {
                        name,
                        content
                      }
                      // Add item via addItem action
                      updateItem(_id, newItem);
                    }}
                    >
                      <FormGroup>
                        <Button
                          style={{
                            position: "absolute",
                            left: "100%",
                            marginLeft: "-2.2rem",
                            marginTop: "-0.8rem"
                          }}
                          color="danger"
                          size="md"

                          onClick={onDeleteClick.bind(this, _id)}
                        >&times;
                  </Button>
                        <Label for="item">Header</Label>
                        <Input
                          type="text"
                          name="name"
                          id="item"
                          defaultValue={name}
                          // value={name}
                          placeholder="Add shopping item"
                          onChange={onChangeName(itemName, index)}
                        />
                        <Label for="item">Content</Label>
                        <Input
                          type="textarea"
                          name="content"
                          id="item"
                          defaultValue={content}
                          // value={content}
                          placeholder="Add shopping item"
                          onChange={onChangeContent(itemName, index)}
                        />
                        <Button
                          color="dark"
                          style={{ marginTop: '2rem' }}
                          block>
                          Change
                </Button>
                      </FormGroup>
                    </Form>
                  </div> :
                  <div>
                    <h2>{name}</h2>
                    <p>{content}</p>
                    <p>{date.replace("T", " ").slice(0, -8)}</p>
                  </div>
                }
              </ListGroupItem>
            </CSSTransition>
          ))}
        </TransitionGroup>
      </ListGroup>
    </Container>
  );
}

MyList.propTypes = {
  getItems: PropTypes.func.isRequired,
  item: PropTypes.object.isRequired,
  isAuthenticated: PropTypes.bool
}

const mapStateToProps = (state) => ({
  item: state.item,
  isAuthenticated: state.auth.isAuthenticated
});

export default connect(
  mapStateToProps,
  { getItems, deleteItem, updateItem }
)(MyList);
import React,{useffect,useState}来自“React”;
进口{
容器、ListGroup、ListGroupItem、按钮、表单、,
FormGroup,
标签,
输入
}来自“反应带”;
从'react transition group'导入{CSTranslation,TransitionGroup};
从'react redux'导入{connect};
从“../actions/itemActions”导入{getItems,deleteItem,updateItem};
从“道具类型”导入道具类型;
const MyList=({getItems,deleteItem,isAuthenticated,item,updateItem})=>{
const[itemName,setItemName]=useState({});
常量[isDeleted,setIsDeleted]=useState(false);
常量createArray=()=>{
常量{items}=item;
const newNames=items.map(item=>item);
setItemName({…newNames});
};
useffect(()=>{
getItems();
createArray();
},[isDeleted]);
const onChangeName=(项,索引)=>{
返回(事件)=>{
const name=event.target.value;
setItemName(prevObjs=>({…prevObjs[index]:{…item[index],name}));
console.log(itemName);
}
}
const onChangeContent=(项目、索引)=>{
返回(事件)=>{
常量内容=event.target.value;
setItemName(prevObjs=>({…prevObjs,索引:{…项[index],内容}}));
}
}
const onDeleteClick=id=>{
删除项目(id);
setIsDeleted(!isDeleted);
};
console.log(itemName);
返回(
{item.items.map({u id,名称,内容,日期},索引)=>(

{是否已验证?
{
e、 预防默认值();
常量{name,content}=itemName[index];
常量newItem={
名称
内容
}
//通过addItem操作添加项
updateItem(_id,newItem);
}}
>
&时代;
标题
内容
改变
:
{name}
{content}

{date.replace(“T”,”).slice(0,-8)}

} ))} ); } MyList.propTypes={ getItems:PropTypes.func.isRequired, 项目:PropTypes.object.isRequired, IsAuthentication:PropTypes.bool } 常量mapStateToProps=(状态)=>({ 项目:状态项, isAuthenticated:state.auth.isAuthenticated }); 导出默认连接( MapStateTops, {getItems,deleteItem,updateItem} )(MyList);
好的。尝试在已装载上提取项目,方法为:

useEffect(()=>{
    getItems()
},[])
并在项目更改时重新创建阵列(在redux存储中):

编辑: 在这种情况下,使用
usemo
可能比使用第二个
useffect
useState
更好

const itemName = useMemo( () => {
        const { items } = item;
        return items.map(item => item);
}, [item.items])

getItems做什么?getItems正在将数据从mongodb上传到item。接下来,我将项目发送到ItemName。我想我知道问题出在哪里(您可能不认为状态更新是异步的),但您能确保显示整个组件吗?好的,回答是我的整个组件很好,它可以工作。非常感谢。我还想知道如何处理addItem操作,但我检查了它是否可以在没有任何更改的情况下工作。我想给你投票,但我必须填写我的个人资料,因为我没有足够的声誉,但将来会这样做。可能吧,因为我通常将此用于onChange和onSubmit函数。如果这是更好的方法,我将尝试学习这些方法并改进我的代码。再次感谢你的帮助。不要担心投票。请尝试我的编辑,使用setState(setItemName)会导致重新渲染,如果可能,请避免。OK,我会尝试,但我必须修改onChangeName和onChangeContent函数。也许我明天会做。
  useEffect(() => {
    const createArray = () => {
        const { items } = item;
        const newNames = items.map(item => item);
        setItemName({ ...newNames });
    };
    createArray();
  }, [item.items]);
const itemName = useMemo( () => {
        const { items } = item;
        return items.map(item => item);
}, [item.items])