【问题标题】:My Table is not re-rendering even it is calling useEffect我的表即使在调用 useEffect 也不会重新渲染
【发布时间】:2021-07-11 04:33:15
【问题描述】:

directoryList 是列表的一种状态,由我的一个组件中的文件详细信息 (filename,keyword,status,checked) 组成。

我的全码加在codesandBox

说明:

  1. 添加一个文本文件并点击上传
  2. 在关键字输入框中输入一个词,然后 在默认行中给出数值
  3. 点击“申请勾选”
  4. 点击“查找”按钮
directoryList = [{
filename:'',
checked: false,
keyword:'',
linestoBecopied:0,
status:""
}]

我有一个名为Find 的按钮。如果我点击按钮,findButtonHandler 将被调用。

我在这里尝试更改状态,值正在更改但 UI 未重新渲染。如果我点击Find 按钮两次,UI 会重新渲染。


   
   useEffect(() => {
     console.log("useEffect called")
    }, [directoryList]);


      const fileChangeHandler = (e) =>
      {
        const files=[]
        console.log("hiiiii")
        for(let i = 0; i< e.target.files.length; i++) {
          files.push(e.target.files[i])
      }
      console.log(files)
      setFiles(files)
    }
      const uploadClickHandler=()=>
      {
        var list=[];
        for(let i=0;i<files.length;i++ )
        {
        var file = files[i];
        console.log(file.name)
        var obj = {
          filename: file.name,
          status:"",
          checked:true,
            keyWord:"",
            linesToBeCopied:""
        }
        list.push(obj);
      }
        setDirectoryList([...list])
        console.log(directoryList)
      
      }

      const applyForCheckHandler = () =>
      {
        const list = [...directoryList]
        list.map((dir,i) => (
          dir.keyWord=keyWord,
          dir.linesToBeCopied=defLines
        ))
        console.log(list)
        setDirectoryList([...list])
        
      }

      const checkBoxHandler = (filename) =>
      {
        console.log("hi")
        var list1 = directoryList
        list1.map((dir,i) => {
          if(i==filename)
          {
          if(dir.checked==true)
           dir.checked=false
          else
           dir.checked=true 
        }})
        console.log(list1)
        setDirectoryList(list1)
      }

      **const findButtonHandler = () =>
      {
        let list1 = [...directoryList]
        for(let i=0;i<files.length;i++)
        {
          let status=""
          var file = files[i]
          list1.map((dir,i) => {
            if(dir.filename==file.name && dir.checked)
            {
              
               var reader = new FileReader();
               reader.onload = function(progressEvent){
               var lines = this.result.split('\n');
               for(var line = 0; line < lines.length; line++){
                 console.log(lines[line])
                 if(lines[line].includes(dir.keyWord)){
                   console.log("text found")
                   status = "Found"
                   dir.status = "Found"
                   break;
                   }
                 else{
                  status="Not Found"
                  dir.status = status
                 }
              }
            };  reader.readAsText(file);
            }
         
        })}
        console.log(list1)
        
      }**

      const saveHandler = () => {
        const formData = new FormData()
        var str = JSON.stringify(directoryList)
        var list = JSON.parse(str);
        var list1 = directoryList
        var filename=""
        console.log(directoryList.length)
        list1.map((dir,i) => {
          console.log(dir.filename+dir.checked)
          if(dir.checked==true && dir.status=='Found')
            filename = filename + dir.filename + ","
        })
        var lines = defLines
        var keyword = keyWord

        for(let i = 0; i< files.length; i++) {
          formData.append('file', files[i])
        }
        formData.append("lines",lines)
        formData.append("keyword",keyword)
        formData.append("filenames",filename)
        
        console.log(lines)
        console.log(keyWord)
        console.log(filename)

        axios.post('http://localhost:8080/save', formData,{
          headers:{
          "Content-Type":"multipart/form-data"
         } })
        .then((response) => {
          fileDownload(response.data,'output.txt')
         
        }).catch(error =>
          {
            console.log(error.message)
          });
      }
    return (
        <>
        <HeadingComponent>
            <h3>Data Quest</h3>
        </HeadingComponent>
        <FirstComponent>
          <SearchDirComponent>
        Select Filesto Upload : <input type='file' name="files" id="inputfile" onChange={fileChangeHandler} multiple></input>
        </SearchDirComponent>
       <FirstButtonComponent>
       <Button
        variant="contained"
        color="default"
        startIcon={<CloudUploadIcon />}
        onClick={uploadClickHandler}
      >
        Upload
      </Button>
      <Button
        variant="contained"
        color="secondary"
        startIcon={<DeleteIcon />}
      >
        Close
      </Button>
       </FirstButtonComponent>
         
        </FirstComponent>
        <SecondComponent>
          <SecondInputComponent>
        <div> Search Keyword :  <OutlinedInput type='text' name="directoryname"  value={keyWord} onChange={(e)=> setkeyword(e.target.value)}style = {{width: 100,height:30,paddingLeft:10}}></OutlinedInput></div>
        <div style={{paddingLeft:150}}> Default Lines <OutlinedInput type='text' name="defaultLines" value={defLines} onChange={(e)=> setDefLines(e.target.value)} style = {{width: 100,height:30,paddingLeft:10}}></OutlinedInput></div>
        <div style={{paddingLeft:150}}>
        <Button
        variant="contained"
        color="primary"
        onClick={applyForCheckHandler}
        style={{fontSize:14 ,width:220,height:27}}
      >
        Apply for checked
      </Button>
        </div>
        </SecondInputComponent>
        <ApplyButtonComponent>
        
        </ApplyButtonComponent>
        </SecondComponent>
       <TableComponent> 
    <TableContainer component={Paper}>
      <Table aria-label="simple table">
        <TableHead>
          <TableRow>
            <TableCell align="center">&nbsp;&nbsp;Select Files</TableCell>
            <TableCell align="center">File Name</TableCell>
            <TableCell align="center">Search Keyword&nbsp;(g)</TableCell>
            <TableCell align="center">Lines to be copied&nbsp;(g)</TableCell>
            <TableCell align="center">Status&nbsp;(g)</TableCell>
          </TableRow>
        </TableHead>
        <TableBody>
          {directoryList.length>0 && directoryList.map((directory,i) => (
            <TableRow key={directory.filename}>
              <TableCell component="th" scope="row" align="center">
               <Checkbox checked={directory.checked} onClick={() => checkBoxHandler(i)} name={directory.filename}></Checkbox></TableCell>
              <TableCell align="center">{directory.filename}</TableCell>
              <TableCell align="center">{directory.keyWord}</TableCell>
              <TableCell align="center">{directory.linesToBeCopied}</TableCell>
              <TableCell align="center">{directory.status}</TableCell>
            </TableRow>
          ))}
        </TableBody>
      </Table>
    </TableContainer>
        </TableComponent>
        { directoryList.length >0 &&
        
        <ButtonComponent>
          <div>
        <Button variant="contained" color="secondary" onClick={findButtonHandler}>
        Find
        </Button></div>
        <div>
        <Button variant="contained" color="primary" style={{paddingLeft: 20}} onClick={saveHandler}>
        Save
       </Button></div>
        </ButtonComponent>} 
        </>
    )
}

【问题讨论】:

  • 调用findButtonHandler方法的按钮在哪里?
  • @edhi.uchiha 我刚刚又添加了几行代码
  • 可能缺少return语句,能否分享完整代码
  • 你能分享代码沙箱中的代码吗??
  • @AjithRam 请检查我的答案

标签: javascript reactjs file dom-events


【解决方案1】:

我看到这里是因为您的名为 directoryList 的状态从未更改,因此您的组件不会触发重新渲染。

请尝试像这样更改您的directoryList 状态:

  const findButtonHandler = () => {
    let list1 = [...directoryList]

     for(let i=0;i<files.length;i++)
     {
       let status=""
       var file = files[i]
       list1.map((dir,i) => {
         if(dir.filename==file.name && dir.checked) {

            var reader = new FileReader();
            reader.onload = function(progressEvent){
            var lines = this.result.split('\n');
            for(var line = 0; line < lines.length; line++){
              console.log(lines[line])
              if(lines[line].includes(dir.keyWord)){
                console.log("text found")
                status = "Found"
                dir.status = "Found"
                break;
                }
              else{
               status="Not Found"
               dir.status = status
              }
           }
         };  reader.readAsText(file);
         }

         list1[i].status = status // add this line
     }
     )}
     console.log(list1)
    setDirectoryList([...list1]);
  };

并查看结果,并记住重新渲染将在您的状态更改时触发。如果你使用了钩子,你必须声明你想要在数组中触发调用 useEffect 的状态。

useEffect(() => {
     console.log("useEffect called")
    }, [directoryList]);

useEffect 将在directoryList 的值发生变化时调用或重新渲染组件

【讨论】:

  • 状态不是一个单一的变量。在 DirectoryList 中,每个文件可能有不同的状态
  • 看,当我点击 Find 按钮时,useEffect 被调用并且能够在 console.log 的帮助下看到状态的变化
  • @AjithRam 请检查我的更新答案,我想你可以添加list1[i].status = status
  • list1[i].status = status is not working ,状态值不会在 UI 中打印,但如果我像 list1[i].status='found' 这样硬编码,它会打印
【解决方案2】:

reader.onload() 是异步函数,所以状态值不会在第一时间改变

【讨论】:

    猜你喜欢
    • 2021-10-28
    • 2019-03-05
    • 1970-01-01
    • 1970-01-01
    • 2020-02-18
    • 1970-01-01
    • 2019-08-09
    • 1970-01-01
    • 2019-07-28
    相关资源
    最近更新 更多