React Modal Updater 在 setState() 后不刷新页面 [英] React Modal Updater doesn't refresh page after setState()

查看:47
本文介绍了React Modal Updater 在 setState() 后不刷新页面的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有人建议我浅拷贝一个对象,因为仅使用 = 符号复制状态对象会指向"对象.到旧状态.

现在,我知道了:我的屏幕上有一个列表,其中的每个项目都是状态数组中的一个元素.每个项目都有自己的变化".按钮,当按下该按钮时,会打开一个反应模式,将所有项目信息输入文本输入,因此我可以更改它并按下更新"按钮.模态中的按钮.按下后,模态应该关闭,列表应该刷新,但最后一件事不会发生.

这是整个组件代码:

import React, { useContext, useEffect, useState } from 'react';import { ThemeContext } from '../../providers/ThemeContext';从 '../../services/axios' 导入 axios;导入'./styles.css';从'react-modal'导入模态;从@material-ui/core"导入{分隔符};Modal.setAppElement('#root')函数 AllInOneProjectPage() {const [projects, setProjects] = useState

I have been advised to shallow copy an object, since copying the state object using only the = sign would "point" to the old state.

Now, I've got this: there's a list on my screen, and each item on it is an element from a state array. Each item has its own "change" button, and when that button is pressed, a react-modal is opened with all the item information into text inputs, so I'd be able to change it and press the "Update" button in the modal. After pressing it, the modal should close and the list should be refreshed, but this last thing doesn't happen.

This is the entire component code:

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;

解决方案

Issue

I think the issue is a simple one; you've used defaultValue for the disabled inputs on the AllInOneProjectPage component. When an input uses the defaultValue prop it makes them uncontrolled inputs, meaning they don't respond to any external changes nor are they controlled by any state.

Solution

Convert these inputs over to controlled inputs by using the value prop instead.

{projects &&
  projects.map((p, i) => (
    <div key={p.id} style={outerDivProject}>
      <div style={projectFields}>
        <h4>Title:</h4>
        <input type="text" name="title" disabled value={p.title} /> // <-- now controlled
      </div>

      <div style={projectFields}>
        <h4>URL:</h4>
        <input type="text" name="url" disabled value={p.url} /> // <-- now controlled
      </div>

      <div style={projectFields}>
        <h4>Techs:</h4>
        <input
          type="text"
          name="techs"
          disabled
          value={p.techs.map((t: any) => t)} // <-- now controlled
        />
      </div>

      <p
        style={changeButtonStyles}
        onClick={() => openModal(p.id, p.title, p.url, p.techs)}
      >
        Alterar
      </p>
    </div>
  ))}

Forked Demo

这篇关于React Modal Updater 在 setState() 后不刷新页面的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆