Reactjs 为什么不是';当我更改状态时,我的React应用程序不会重新渲染吗?
我有一个React应用程序,它使用以下模型:Reactjs 为什么不是';当我更改状态时,我的React应用程序不会重新渲染吗?,reactjs,typescript,Reactjs,Typescript,我有一个React应用程序,它使用以下模型: export interface DataModel { itemId: string, itemName: string, } 我为模型定义了一个初始值,如下所示: export const INIT_ITEM:DataModel = { itemId: "", itemName: "", } 这在Dashbaord组
export interface DataModel {
itemId: string,
itemName: string,
}
我为模型定义了一个初始值,如下所示:
export const INIT_ITEM:DataModel = {
itemId: "",
itemName: "",
}
这在Dashbaord组件中使用,该组件显示一个表单,允许用户设置名称、minimumValue和maximumValue。名称是必需的;minimumValue和maximumValue不存在,但如果它们都存在,则maximumValue需要大于minimumValue。此验证在提交表单时完成。这是仪表板组件:
interface ErrorHolder { // Holds error strings
selectedItems: string,
selection1: string,
selection2: string,
valid: boolean
}
const INIT_VALIDATION:ErrorHolder = {
selectedItems: "",
selection1: "",
selection2: "",
valid: false
}
// availableItems is an array of <DataModel>, prepopulated with available options
// selectedItems is an array of <DataModel>, and is initially empty
// selection1 and selection2 are both <DataModel> objects, which are initialised as above
//
// The items from availableItems are displayed with checkboxes. The user must select at least one item to // display on the Dashboard; the list of selected items is stored as selectedItems
// The user must also select an item to be 'selection1' and a different item to be 'selection2'
//
const Dashboard = ( {availableItems, selectedItems, setSelectedItems, selection1, setSelection1, selection2, setSelection2} ) => {
const [valid, setValid] = useState<ErrorHolder>(INIT_VALIDATION); // Initialise error strings
const handleChangeItemSelected = (event:React.ChangeEvent<HTMLInputElement>, checked:boolean) => {
const itemId:number = event.target.value;
if(checked) {
// Checkbox is checked, so this item should be shown
const newSelectedItems = [...selectedItems];
const fullItem = availableItems.filter(item => item.itemId === itemId);
newSelectedItems .push(fullItem[0]);
setSelectedItems(newSelectedItems );
}else {
// Checkbox is not checked, so this item should not be shown
const newSelectedItems = selectedItems.filter(item=> item.itemId !== itemId);
setSelectedItems(newSelectedItems );
}
}
const handleSelectItem = (event: { target: HTMLSelectElement }) => {
let thisItem:DataModel|undefined = undefined;
let selectedId = parseInt(event.target.value);
if(selectedId !== 0) {
const findItem = availableItems.filter(item => item.itemId === selectedId);
thisItem = findItem[0];
}
// Check which item is being changed
switch(event.target.id) {
case 'selection1':
setSelection1(thisItem);
break;
case 'metric2Select':
setSelection2(thisItem);
break;
}
}
const handleSubmit = (event: SyntheticEvent) => {
event.preventDefault();
// Validate
let tempValid:ErrorHolder = INIT_VALIDATION;
tempValid.valid = true;
// Validate everything - set error if found
if(selectedItems.length === 0) { // There must be at least 1 selected item
tempValid.valid = false;
tempValid.selectedItems = "Please select at least one item";
}
// Make sure 2 different items are selected for selection 1 and selection 2
if(!selection1) {
tempValid.valid = false;
tempValid.selection1 = "Please select two items to show on the chart";
}else if(!selection2) {
tempValid.valid = false;
tempValid.selection2 = "Please select two items to show on the chart";
}else if(selection1.itemId === selection2.itemId) {
tempValid.valid = false;
tempValid.selection2= "Please select two different items to show on the chart";
}
}
setValid(tempValid);
}
return (
<form onSubmit = { handleSubmit }>
// List available options
<div>{valid.selectedItems}</div> // Display error message for selected items
<table>
<thead>
<tr>
<td>Name</td>
<td>Show</td>
</tr>
</thead>
<tbody>
{
availableItems.map((item) => { // List all available items with checkboxes
<tr key={item.itemId}>
<td>{item.itemName}</td>
<td><Checkbox value={item.itemId}
onChange={handleChangeItemSelected}
checked={selectedItems.includes(item)} /></td>
</tr>
})
}
</tbody>
</table>
<select id = "selection1" onChange = { event => handleSelectItem(event) }
value = { selection1?.itemId}>
<option key="sel1" value="0">Please Select</option>
{
availableItems.map((item) => <option key={item.itemId} value={item.itemId}>{item.itemName}</option>;
}
</select>
<div>{valid.selection1}</div>
<select id = "selection2" onChange = { event => handleSelectItem(event) }
value = { selection2?.itemId}>
<option key="sel2" value="0">Please Select</option>
{
availableItems.map((item) => <option key={item.itemId} value={item.itemId}>{item.itemName}</option>;
}
</select>
<div>{valid.selection2}</div>
</form>
);
}
export default Dashboard;
interface ErrorHolder{//保存错误字符串
selectedItems:string,
选择1:string,
选择2:字符串,
有效值:布尔值
}
const INIT_验证:ErrorHolder={
selectedItems:“”,
选择1:“”,
选择2:“,
有效:假
}
//availableItems是一个数组,预先填充了可用选项
//selectedItems是的数组,最初为空
//selection1和selection2都是对象,其初始化如上所述
//
//availableItems中的项目显示为复选框。用户必须至少选择一项//显示在仪表板上;所选项目的列表存储为selectedItems
//用户还必须选择一个项目作为“selection1”,另一个项目作为“selection2”
//
常量仪表板=({availableItems,selectedItems,setSelectedItems,selection1,setSelection1,selection2,setSelection2})=>{
const[valid,setValid]=useState(初始化验证);//初始化错误字符串
const handleChangeItemSelected=(事件:React.ChangeEvent,选中:布尔)=>{
const itemId:number=event.target.value;
如果(选中){
//复选框已选中,因此应显示此项
const newSelectedItems=[…selectedItems];
const fullItem=availableItems.filter(item=>item.itemId===itemId);
newSelectedItems.push(fullItem[0]);
设置selecteditems(newSelectedItems);
}否则{
//复选框未选中,因此不应显示此项
const newSelectedItems=selectedItems.filter(item=>item.itemId!==itemId);
设置selecteditems(newSelectedItems);
}
}
const handleSelectItem=(事件:{target:HTMLSelectElement})=>{
设此项:数据模型|未定义=未定义;
让selectedId=parseInt(event.target.value);
如果(选择EDID!==0){
const findItem=availableItems.filter(item=>item.itemId===selectedId);
thisItem=findItem[0];
}
//检查正在更改的项目
开关(event.target.id){
案例“选择1”:
设置选项1(本项目);
打破
案例“metric2Select”:
设置选项2(本项目);
打破
}
}
const handleSubmit=(事件:SyntheticEvent)=>{
event.preventDefault();
//证实
让tempValid:ErrorHolder=INIT_验证;
tempValid.valid=true;
//验证所有内容-如果发现,则设置错误
如果(selectedItems.length==0){//则必须至少有1个选定项
tempValid.valid=false;
tempValid.selectedItems=“请至少选择一项”;
}
//确保为选项1和选项2选择了两个不同的项目
如果(!selection1){
tempValid.valid=false;
tempValid.selection1=“请选择两个要显示在图表上的项目”;
}如果(!selection2),则为else{
tempValid.valid=false;
tempValid.selection2=“请选择两个要在图表上显示的项目”;
}else if(selection1.itemId==selection2.itemId){
tempValid.valid=false;
tempValid.selection2=“请选择两个不同的项目以显示在图表上”;
}
}
setValid(tempValid);
}
返回(
//列出可用选项
{valid.selectedItems}//显示所选项目的错误消息
名称
显示
{
availableItems.map((项)=>{//使用复选框列出所有可用项
{item.itemName}
})
}
handleSelectItem(事件)}
值={selection1?.itemId}>
请选择
{
availableItems.map((item)=>{item.itemName};
}
{valid.selection1}
handleSelectItem(事件)}
值={selection2?.itemId}>
请选择
{
availableItems.map((item)=>{item.itemName};
}
{valid.selection2}
);
}
导出默认仪表板;
我遇到的问题是,如果我输入无效数据(例如不选择任何内容,为selection1和selection2选择相同的内容等)并单击“提交”,则不会显示错误。如果我执行控制台日志,我可以看到valid
变量设置正确,但组件似乎没有重新渲染以显示它
我做错了什么?在每次调用
handleSubmit
时,您都在对同一对象进行变异INIT\u VALIDATION
,并且将同一对象传递给setState
函数不会触发重新渲染器
如果您通过替换
let tempValid:ErrorHolder = INIT_VALIDATION
与
我希望它能工作。
let
不是问题的一部分,但是如果你不改变变量本身,你可以使用const
。谢谢!这正是我需要做的;现在一切都很好!
const tempValid:ErrorHolder = {...INIT_VALIDATION}