在 React 中添加新项目后,本地状态会重置
Local state gets reset after adding a new item in React
我正在制作一个小型 React 应用程序来跟踪家庭作业。您应该能够添加多个日期,并在这些日期内添加多个作业。我可以将日期打印到屏幕上,也可以打印出一天的多个作业。然而,在添加另一个日期后,存储所有先前日期分配的本地状态将被清除,因此每个日期的分配都会消失。所有日期仍显示在屏幕上,但其中的分配不再存在,也不再处于状态。添加新日期时,如何让分配保留在屏幕上并处于状态?这是我需要本地存储的东西吗?如果能得到任何帮助,我将不胜感激。下面是我的代码:
import Button from './Button';
import DatesInput from './DatesInput';
import DatesDisplay from './DatesDisplay';
const AssignmentCalendar = () => {
const [dates, setDates] = useState([]);
const addDate = (date) => {
setDates(dates.concat(date))
}
return (
<main className="main-display">
<h3>Assignment Calendar</h3>
<h4 className="dates-Title">Dates</h4>
<Button
text='Add Date'
color='green'
/>
<DatesInput dates={dates} addDate={addDate}/>
<DatesDisplay dates={dates} />
</main>
)
}
export default AssignmentCalendar
import React, { useState } from 'react'
import Button from './Button'
const DatesInput = ({ addDate }) => {
const [ date, setDate ] = useState('')
const typeInDate = (e) => {
setDate(e.target.value)
}
const submitDate = (e) => {
e.preventDefault();
addDate(date)
setDate('')
}
return (
<form className='dates-input' onSubmit={submitDate}>
<label className='input-label'>Please enter a new date...</label>
<input type='text' value={date} onChange={typeInDate} ></input>
<Button text='Submit' />
</form>
)
}
export default DatesInput
import React from 'react'
import Date from './Date';
import { v4 as uuidv4 } from 'uuid';
const DatesDisplay = ({ dates }) => {
return (
<div className='assignment-display'>
{dates.map((date) => {
return (
<div key={uuidv4()}>
<Date date={date}/>
</div>
)
})}
</div>
)
}
export default DatesDisplay
import React, { useState } from 'react';
import Assignments from './Assignments';
import Button from './Button';
const Date = ({ date }) => {
const [assignments, setAssignments] = useState([]);
const addAssignment = (assignment) => {
setAssignments(assignments.concat(assignment))
}
return (
<div>
<h5>{date} <Button text='Add Assignment'/></h5>
<div className='assignment-display'>
<Assignments assignments={assignments} addAssignment={addAssignment} />
</div>
</div>
)
}
export default Date
import React from 'react'
import AssignmentInput from './AssignmentInput';
import AssignmentDisplay from './AssignmentDisplay';
const Assignments = ({ assignments, addAssignment }) => {
return (
<div>
<AssignmentInput addAssignment={addAssignment} />
<AssignmentDisplay assignments={assignments} />
</div>
)
}
export default Assignments
import React, { useState } from 'react'
import Button from './Button';
const AssignmentInput = ({ addAssignment }) => {
const [assignment, setAssignment] = useState({
name: '',
subject: '',
});
const handleAddName = (e) => {
setAssignment({
name: e.target.value,
subject: assignment.subject,
})
}
const handleAddsubject = (e) => {
setAssignment({
name: assignment.name,
subject: e.target.value,
})
}
const submitNewAssignment = (e) => {
e.preventDefault();
addAssignment(assignment);
setAssignment({
name: '',
subject: '',
});
}
return (
<form onSubmit={submitNewAssignment}>
<label>Please enter a new assignment...</label>
<input type='text' placeholder='Assignment name' value={assignment.name} onChange={handleAddName}></input>
<input type='text' placeholder='Subject' value={assignment.subject} onChange={handleAddsubject}></input>
<Button text='Submit' />
</form>
)
}
export default AssignmentInput
import React from 'react'
import { v4 as uuidv4 } from 'uuid';
import Assignment from './Assignment';
const AssignmentDisplay = ({ assignments }) => {
return (
<div>
{assignments.map((assignment) => {
return (
<div key={uuidv4()}>
<Assignment name={assignment.name} subject={assignment.subject}/>
</div>
)
})}
</div>
)
}
export default AssignmentDisplay
import React from 'react'
import { FaTimes, FaCheckCircle } from 'react-icons/fa'
const Assignment = ({ name, subject }) => {
return (
<div>
<FaCheckCircle style={{color: 'green', cursor: 'pointer'}} />
<h6 className='assignment-names'>
{name}
<FaTimes
style={{color: 'red', cursor: 'pointer'}}
/>
</h6>
<p className='assignment-date'>
{subject}
</p>
</div>
)
}
export default Assignment
问题
当您为每个元素生成一个新的 GUID 时,您实际上是在为映射到 DateDisplay
中的每个 Date
组件使用随机 React 密钥。
const DatesDisplay = ({ dates }) => {
return (
<div className='assignment-display'>
{dates.map((date) => {
return (
<div key={uuidv4()}> // <-- new unique key each render
<Date date={date}/>
</div>
)
})}
</div>
)
}
如果每个元素的 React 键在渲染之间不稳定,那么 React 会将其解释为一个新组件并卸载先前的“实例”并安装一个新的“实例”,从而丢弃任何组件状态。
解决方案
一个理想的解决方案可能是将赋值数组存储在 AssignmentCalendar
组件的 dates
状态数组中,但要专门解决这个问题,您只需要为每个 date
元素处于 dates
状态。为此,我建议在将新日期添加到状态时将 GUID 生成移动到 AssignmentCalendar
组件中。
const AssignmentCalendar = () => {
const [dates, setDates] = useState([]);
const addDate = (date) => {
setDates(dates.concat({
id: uuidv4(), // <-- generate GUID id property
date,
}));
};
return (
<main className="main-display">
<h3>Assignment Calendar</h3>
<h4 className="dates-Title">Dates</h4>
<button type="button">Add Date</button>
<DatesInput dates={dates} addDate={addDate} />
<DatesDisplay dates={dates} />
</main>
);
};
在映射时解构DatesDisplay
中的date
和id
,仍然使用id
作为React key。
const DatesDisplay = ({ dates }) => {
return (
<div className="assignment-display">
{dates.map(({ date, id }) => (
<div key={id}> // <-- now a stable id
<Date date={date} />
</div>
))}
</div>
);
};
我正在制作一个小型 React 应用程序来跟踪家庭作业。您应该能够添加多个日期,并在这些日期内添加多个作业。我可以将日期打印到屏幕上,也可以打印出一天的多个作业。然而,在添加另一个日期后,存储所有先前日期分配的本地状态将被清除,因此每个日期的分配都会消失。所有日期仍显示在屏幕上,但其中的分配不再存在,也不再处于状态。添加新日期时,如何让分配保留在屏幕上并处于状态?这是我需要本地存储的东西吗?如果能得到任何帮助,我将不胜感激。下面是我的代码:
import Button from './Button';
import DatesInput from './DatesInput';
import DatesDisplay from './DatesDisplay';
const AssignmentCalendar = () => {
const [dates, setDates] = useState([]);
const addDate = (date) => {
setDates(dates.concat(date))
}
return (
<main className="main-display">
<h3>Assignment Calendar</h3>
<h4 className="dates-Title">Dates</h4>
<Button
text='Add Date'
color='green'
/>
<DatesInput dates={dates} addDate={addDate}/>
<DatesDisplay dates={dates} />
</main>
)
}
export default AssignmentCalendar
import React, { useState } from 'react'
import Button from './Button'
const DatesInput = ({ addDate }) => {
const [ date, setDate ] = useState('')
const typeInDate = (e) => {
setDate(e.target.value)
}
const submitDate = (e) => {
e.preventDefault();
addDate(date)
setDate('')
}
return (
<form className='dates-input' onSubmit={submitDate}>
<label className='input-label'>Please enter a new date...</label>
<input type='text' value={date} onChange={typeInDate} ></input>
<Button text='Submit' />
</form>
)
}
export default DatesInput
import React from 'react'
import Date from './Date';
import { v4 as uuidv4 } from 'uuid';
const DatesDisplay = ({ dates }) => {
return (
<div className='assignment-display'>
{dates.map((date) => {
return (
<div key={uuidv4()}>
<Date date={date}/>
</div>
)
})}
</div>
)
}
export default DatesDisplay
import React, { useState } from 'react';
import Assignments from './Assignments';
import Button from './Button';
const Date = ({ date }) => {
const [assignments, setAssignments] = useState([]);
const addAssignment = (assignment) => {
setAssignments(assignments.concat(assignment))
}
return (
<div>
<h5>{date} <Button text='Add Assignment'/></h5>
<div className='assignment-display'>
<Assignments assignments={assignments} addAssignment={addAssignment} />
</div>
</div>
)
}
export default Date
import React from 'react'
import AssignmentInput from './AssignmentInput';
import AssignmentDisplay from './AssignmentDisplay';
const Assignments = ({ assignments, addAssignment }) => {
return (
<div>
<AssignmentInput addAssignment={addAssignment} />
<AssignmentDisplay assignments={assignments} />
</div>
)
}
export default Assignments
import React, { useState } from 'react'
import Button from './Button';
const AssignmentInput = ({ addAssignment }) => {
const [assignment, setAssignment] = useState({
name: '',
subject: '',
});
const handleAddName = (e) => {
setAssignment({
name: e.target.value,
subject: assignment.subject,
})
}
const handleAddsubject = (e) => {
setAssignment({
name: assignment.name,
subject: e.target.value,
})
}
const submitNewAssignment = (e) => {
e.preventDefault();
addAssignment(assignment);
setAssignment({
name: '',
subject: '',
});
}
return (
<form onSubmit={submitNewAssignment}>
<label>Please enter a new assignment...</label>
<input type='text' placeholder='Assignment name' value={assignment.name} onChange={handleAddName}></input>
<input type='text' placeholder='Subject' value={assignment.subject} onChange={handleAddsubject}></input>
<Button text='Submit' />
</form>
)
}
export default AssignmentInput
import React from 'react'
import { v4 as uuidv4 } from 'uuid';
import Assignment from './Assignment';
const AssignmentDisplay = ({ assignments }) => {
return (
<div>
{assignments.map((assignment) => {
return (
<div key={uuidv4()}>
<Assignment name={assignment.name} subject={assignment.subject}/>
</div>
)
})}
</div>
)
}
export default AssignmentDisplay
import React from 'react'
import { FaTimes, FaCheckCircle } from 'react-icons/fa'
const Assignment = ({ name, subject }) => {
return (
<div>
<FaCheckCircle style={{color: 'green', cursor: 'pointer'}} />
<h6 className='assignment-names'>
{name}
<FaTimes
style={{color: 'red', cursor: 'pointer'}}
/>
</h6>
<p className='assignment-date'>
{subject}
</p>
</div>
)
}
export default Assignment
问题
当您为每个元素生成一个新的 GUID 时,您实际上是在为映射到 DateDisplay
中的每个 Date
组件使用随机 React 密钥。
const DatesDisplay = ({ dates }) => {
return (
<div className='assignment-display'>
{dates.map((date) => {
return (
<div key={uuidv4()}> // <-- new unique key each render
<Date date={date}/>
</div>
)
})}
</div>
)
}
如果每个元素的 React 键在渲染之间不稳定,那么 React 会将其解释为一个新组件并卸载先前的“实例”并安装一个新的“实例”,从而丢弃任何组件状态。
解决方案
一个理想的解决方案可能是将赋值数组存储在 AssignmentCalendar
组件的 dates
状态数组中,但要专门解决这个问题,您只需要为每个 date
元素处于 dates
状态。为此,我建议在将新日期添加到状态时将 GUID 生成移动到 AssignmentCalendar
组件中。
const AssignmentCalendar = () => {
const [dates, setDates] = useState([]);
const addDate = (date) => {
setDates(dates.concat({
id: uuidv4(), // <-- generate GUID id property
date,
}));
};
return (
<main className="main-display">
<h3>Assignment Calendar</h3>
<h4 className="dates-Title">Dates</h4>
<button type="button">Add Date</button>
<DatesInput dates={dates} addDate={addDate} />
<DatesDisplay dates={dates} />
</main>
);
};
在映射时解构DatesDisplay
中的date
和id
,仍然使用id
作为React key。
const DatesDisplay = ({ dates }) => {
return (
<div className="assignment-display">
{dates.map(({ date, id }) => (
<div key={id}> // <-- now a stable id
<Date date={date} />
</div>
))}
</div>
);
};