Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Reactjs 为什么不是';当我更改状态时,我的React应用程序不会重新渲染吗?_Reactjs_Typescript - Fatal编程技术网

Reactjs 为什么不是';当我更改状态时,我的React应用程序不会重新渲染吗?

Reactjs 为什么不是';当我更改状态时,我的React应用程序不会重新渲染吗?,reactjs,typescript,Reactjs,Typescript,我有一个React应用程序,它使用以下模型: export interface DataModel { itemId: string, itemName: string, } 我为模型定义了一个初始值,如下所示: export const INIT_ITEM:DataModel = { itemId: "", itemName: "", } 这在Dashbaord组

我有一个React应用程序,它使用以下模型:

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}