【发布时间】:2021-07-04 16:38:18
【问题描述】:
有人建议我浅复制一个对象,因为仅使用= 符号复制状态对象会“指向”旧状态。
现在,我知道了:我的屏幕上有一个列表,其中的每个项目都是状态数组中的一个元素。每个项目都有自己的“更改”按钮,当按下该按钮时,会打开一个反应模式,其中包含所有项目信息到文本输入中,所以我可以更改它并按下“更新”按钮模态的。按下后,模态框应该关闭并且列表应该被刷新,但是最后这件事没有发生。
这是整个组件代码:
import React, { useContext, useEffect, useState } from 'react';
import { ThemeContext } from '../../providers/ThemeContext';
import axios from '../../services/axios';
import './styles.css';
import Modal from 'react-modal';
import { Divider } from '@material-ui/core';
Modal.setAppElement('#root')
function AllInOneProjectPage() {
const [projects, setProjects] = useState<any[]>([]);
const { theme } = useContext(ThemeContext);
const [isModalOpen, setIsModalOpen] = useState(false);
const [id, setId] = useState('');
const [title, setTitle] = useState('');
const [url, setUrl] = useState('');
const [techs, setTechs] = useState<any[]>([]);
const openModal = (idModal: string, title: string, url: string, techs: any[]) => {
setId(idModal);
setTitle(title);
setUrl(url);
setTechs(techs);
setIsModalOpen(true);
}
const closeModal = () => {
setIsModalOpen(false);
}
const updateProjects = async () => {
const res = await axios.get('list');
res.data.status === 1 && setProjects(res.data.projects);
};
useEffect(() => {
updateProjects();
}, []);
const onUpdateProject = async () => {
const newTitle = (document.getElementById(`modal_title_${id}`) as HTMLInputElement)?.value;
const newUrl = (document.getElementById(`modal_url_${id}`) as HTMLInputElement)?.value;
const techsArray = (document.getElementById(`modal_techs_${id}`) as HTMLInputElement)?.value;
const filteredTechs = techsArray.split(',').filter(tech => {
if(tech !== '')
if(tech !== ' ')
return tech;
});
await axios.patch(`update/${id}`, { title: newTitle, url: newUrl, techs: filteredTechs });
setProjects(projects.map(p => id === p.id ? { ...p, title: newTitle, url: newUrl, techs: filteredTechs } : p));
setIsModalOpen(false);
console.log(projects.map(p => id === p.id ? { ...p, title: newTitle, url: newUrl, techs: filteredTechs } : p));
};
return (
<div style={{
width: '100vw',
minHeight: 'calc(100vh - 64px)',
backgroundColor: theme.bg,
margin: '0',
display: 'flex',
justifyContent: 'space-around',
flexWrap: 'wrap'
}}>
{ projects && projects.map((p, i) => <div key={p.id} style={{
display: 'flex',
flexDirection: 'column',
width: '550px',
height: '300px',
border: '1px solid blue',
margin: '50px'
}}>
<div style={{ backgroundColor: 'green', height: '100%', display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'space-around' }}>
<div style={{display: 'flex', flexDirection: 'column', width: '80%'}}>
<h4>Title:</h4>
<input type="text" name="title" disabled defaultValue={ p.title }/>
</div>
<div style={{display: 'flex', flexDirection: 'column', width: '80%'}}>
<h4>URL:</h4>
<input type="text" name="url" disabled defaultValue={ p.url }/>
</div>
<div style={{display: 'flex', flexDirection: 'column', width: '80%'}}>
<h4>Techs:</h4>
<input type="text" name="techs" disabled defaultValue={ p.techs.map((t: any) => t) }/>
</div>
<a style={{textDecoration: 'underline', color: 'darkblue', cursor: 'pointer' }} onClick={() => openModal(p.id, p.title, p.url, p.techs)}>Alterar</a>
</div>
</div>) }
<Modal isOpen={isModalOpen} style={{
content: {
display: 'flex',
flexDirection: 'column',
maxWidth: '450px',
height: '280px',
margin: 'auto',
backgroundColor: 'lightgrey'
},
overlay: {
backgroundColor: 'rgba(0, 0, 0, 0.85)'
}
}}>
<div className="modal-header" style={{ display: 'flex', justifyContent: 'space-between' }}>
<h1>Edit { title }</h1>
<button onClick={closeModal} style={{ width: '90px', height: '20px', margin: 'auto 0' }}>Close</button>
</div>
<Divider />
<div style={{ width: '80%', margin: '10px auto 0 auto'}}>
<h2>Title: </h2>
<input type="text" name="title" id={`modal_title_${id}`} defaultValue={ title } style={{ width: '90%' }}/>
</div>
<div style={{ width: '80%', margin: '10px auto 0 auto'}}>
<h2>URL: </h2>
<input type="text" name="title" id={`modal_url_${id}`} defaultValue={ url } style={{ width: '90%' }}/>
</div>
<div style={{ width: '80%', margin: '10px auto 0 auto'}}>
<h2>Techs: </h2>
<input type="text" name="title" id={`modal_techs_${id}`} defaultValue={ techs } style={{ width: '90%' }}/>
</div>
<button onClick={ () => onUpdateProject() } style={{ width: '90px', margin: '10px auto 0 auto' }}>Update</button>
</Modal>
</div>
);
}
export default AllInOneProjectPage;
【问题讨论】:
-
感谢@AjeetShah 的澄清,我会这样做的!但我认为他会被标记,我遵循了 stachexchange 上的“指南”,上面说...无论如何,我现在正在做,再次感谢:D
-
您的
projects状态是否真的 没有更新,或者您只是在状态更新后在控制台日志中看到当前尚未更新的状态? IE。setProjects(projects.map( .... ));然后console.log(projects.map( .... ));日志将是当前状态。 -
控制台日志确实显示了已经更新的数组,但是屏幕上的主数组应该在模态关闭后立即更新。该日志有效,因为我在其上使用了与地图相同的逻辑
-
除了尝试功能状态更新 (
setProjects(projects => projects.map( .... )) 我有点难过。认为您可以创建一个 running 代码框来重现我们可以在其中进行调试的更新问题? -
哦,抱歉,我有点忙。我相信我能够在您的沙盒中重现您的问题,但还没有机会进行调查,尽管我会在这里稍等片刻。 Ajeet,如果您已经在看这个,请随时继续。
标签: reactjs use-state react-dom react-modal