1

我在下面有一个图表和一个输入字段。基本上用户可以提出问题,图表会相应地改变。这是它的样子

在此处输入图像描述

这是下面的代码示例(忽略 CoreUI 语法)

<CRow>
   <CCol xs="12" sm="12" lg="12">
      <CCard id="answerScreen" style={{height: "500px"}}>
      {
      !tempResponse.loading?  tempResponse.data.map(value => (  
      <ChartRender
         key={uuidv4()}
         data={value} 
         />
      ))
      :  
      <Loader/>
      }
      </CCard>
   </CCol>
</CRow>

<CRow>
   <CCol xs="12" sm="12" lg="12">
      <CCard>
        
            <CCardBody>
               <CForm className="form-horizontal">
                  <CFormGroup>
                           <CInputGroup size="lg" className="input-prepend">
                              <CInputGroupPrepend>
                                 <CInputGroupText className="">@Ask</CInputGroupText>
                              </CInputGroupPrepend>
                              <CInput 
                              size="16" 
                              type="text" 
                              value={userInput || ""}
                              onChange={e=> handleTextBoxInput(e)}
                              onClick={e=> handleTextBoxClick(e)}   
                              onKeyPress={e => handleTextBoxEnter(e)}
                              id="userQuery"
                              />
                            
                              <CInputGroupAppend>
                                 <CButton color="primary">Send</CButton>
                              </CInputGroupAppend>
                           </CInputGroup>
                  </CFormGroup>
               </CForm>
            </CCardBody>
        
      </CCard>
   </CCol>
</CRow>

这就是我定义我的状态的方式

const [userInput, setUserInput] = React.useState("");
const [tempResponse, setTempResponse] = React.useState({
        data: []
})

我怀疑这部分代码的问题

<CInput 
   size="16" 
   type="text" 
   value={userInput || ""}
   onChange={e=> handleTextBoxInput(e)}
   onClick={e=> handleTextBoxClick(e)}   
   onKeyPress={e => handleTextBoxEnter(e)}
   id="userQuery"
/>

我什至尝试添加useCallback这样的onChange功能

const handleTextBoxInput =  useCallback(e =>{   
        e.preventDefault();
        setUserInput(e.target.value)
}, [])

但没有帮助。我什至读过memo但不确定在哪里或如何在我的情况下应用它。我究竟做错了什么?

观察

如前所述@Matthew,箭头语法每次都会创建一个不同的回调,这有助于重新渲染,因此必须删除。

但即使在删除它之后,每次按下一个键时图表都会重新呈现。我正在使用Chartjswhich在canvas内部使用。有Chartjs问题吗?

4

2 回答 2

2

您对有问题的代码是正确的。

<CInput 
   size="16" 
   type="text" 
   value={userInput || ""}
   onChange={e=> handleTextBoxInput(e)} // performance issue
   onClick={e=> handleTextBoxClick(e)}  // performance issue 
   onKeyPress={e => handleTextBoxEnter(e)} // performance issue
   id="userQuery"
/>

当上述代码多次运行时,每次都会重新创建函数。因此,与其这样做,以下内容就足够了

<CInput 
   size="16" 
   type="text" 
   value={userInput || ""}
   onChange={handleTextBoxInput}
   onClick={handleTextBoxClick}
   onKeyPress={handleTextBoxEnter}
   id="userQuery"
/>

useCallback钩子返回一个回调函数。您可以简单地将返回值用作正常的事件回调。

于 2021-05-17T05:05:37.870 回答
1

在您的输入中,每次按键都会触发两个事件 -onKeyPress并且onChange- 删除onKeyPress.

我怀疑更新 tempResponse的handleTextBoxEnter调用。setTempResponse设置 UI 所依赖的状态将触发重新渲染。

您还应该使用onSubmit事件处理表单提交。如果一个元素在表单内具有焦点并且按下了输入按钮 - 它会在提交时触发。

<form onSubmit={handleTextBoxEnter}></form>

此外,如果一个键发生变化,React 将重新渲染。您正在调用密钥中的函数,因此每次更新都会更新。

tempResponse.data.map((value, i) => (  
 <ChartRender key={`chart-${i}`} data={value} />
))

仅供参考,手动为密钥过度创建 UUID。

export const YourComponent = (): JSX.Element => {
  const [userInput, setUserInput] = useState('');
  const [tempResponse, setTempResponse] = useState({ data: [], loading: true });

  useEffect(()=>{
    // handle initial data loading and set loading to false
  }, [])

  const handleSubmit = (e) => {
    e.preventDefault();
    setTempResponse(your_state_data);
  };

  // e.preventDefault shouldn't be used here and is not required
  const handleChange = ({ target }) => setUserInput(target.value);

  if (tempResponse.loading) {
    return <Loading />;
  }

  // action is set to # for iOS - an action is required to show the virtual submit button on the keyboard
  return (
    <>
      <form action="#" onSubmit={handleSubmit}>
        <input defaultValue={userInput} onChange={handleChange} type="text" />
        <button type="submit">Submit</button>
      </form>
      {!!tempResponse.length &&
        tempResponse.data.map((value, i) => (
          <ChartRender key={`chart-${i}`} data={value} />
        ))}
    </>
  );
};

于 2021-05-17T06:47:40.437 回答