我无法在条件渲染时使 useEffect 正确读取输入

我正在尝试创建一个具有“静态”模式的输入组件。在这种模式下,输入被包含输入值的跨度替换。在这个问题中,我使用范围输入。


import React from 'react';

import ReactDOM from 'react-dom';


const { useState, useEffect, } = React;


const RangeInput = ({

  inputID, min, max, defaultValue, children,

}) => {

  const [valueAfterStaticChange, setValueAfterStaticChange] = useState(

    defaultValue

  );

  const [isStatic, setIsStatic] = useState(false);

  useEffect(

    () => () => {

      // do this before component unmounts and when 'isStatic' changes,

      // but only when 'isStatic' is true

      isStatic

        || setValueAfterStaticChange(document.getElementById(inputID).value);

    },

    [isStatic]

  );

  return (

    <div>

      <label htmlFor={inputID}>{children}</label>

      <span style={{ display: isStatic || 'none', }}>

        {valueAfterStaticChange}

      </span>

      <input

        type="range"

        min={min}

        max={max}

        defaultValue={valueAfterStaticChange}

        id={inputID}

        style={{ display: isStatic && 'none', }}

      />

      <button

        onClick={() => {

          setIsStatic(!isStatic);

        }}

      >

        Toggle Static

      </button>

    </div>

  );

};


ReactDOM.render(

  <RangeInput inputID="myID" min={0} max={100} defaultValue={50}>

    My Range Input

  </RangeInput>,

  document.getElementById('root')

);

上面的代码有效。但它用于display: none模拟“无渲染”。我认为我可以通过以下逻辑完成实际卸载:


// all unchanged until... 


  return (

    <div>

      <label htmlFor={inputID}>{children}</label>

      {isStatic ? (

        <span>{valueAfterStaticChange}</span>

      ) : (

        <input

          type="range"

          min={min}

          max={max}

          defaultValue={valueAfterStaticChange}

          id={inputID}

        />

      )}

      <button

        onClick={() => {

          setIsStatic(!isStatic);

        }}

      >

        Toggle Static

      </button>

    </div>

  );

};

不知何故,我的useEffect返回函数将无法正确读取输入,因为它实际上已卸载。我认为使用返回函数 inuseEffect会导致一个函数会在组件卸载之前运行。我究竟做错了什么?


慕尼黑的夜晚无繁华
浏览 225回答 2
2回答

手掌心

除非在卸载时有理由获取该值,否则您似乎可以在该值发生变化时对其进行跟踪。这样你就根本不需要useEffect:const RangeInput = ({ inputID, min, max, defaultValue, children }) => {&nbsp; const [value, setValue] = useState(defaultValue); // <-- keep track of value&nbsp; const [isStatic, setIsStatic] = useState(false);&nbsp; return (&nbsp; &nbsp; <div>&nbsp; &nbsp; &nbsp; <label htmlFor={inputID}>{children}</label>&nbsp; &nbsp; &nbsp; {isStatic ? (&nbsp; &nbsp; &nbsp; &nbsp; <span>{value}</span>&nbsp; &nbsp; &nbsp; ) : (&nbsp; &nbsp; &nbsp; &nbsp; <input&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; type="range"&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; min={min}&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; max={max}&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; defaultValue={value}&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; onChange={e => setValue(e.target.value)} // <-- Set value onChange&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; id={inputID}&nbsp; &nbsp; &nbsp; &nbsp; />&nbsp; &nbsp; &nbsp; )}&nbsp; &nbsp; &nbsp; <button&nbsp; &nbsp; &nbsp; &nbsp; onClick={() => {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; setIsStatic(!isStatic);&nbsp; &nbsp; &nbsp; &nbsp; }}&nbsp; &nbsp; &nbsp; >&nbsp; &nbsp; &nbsp; &nbsp; Toggle Static&nbsp; &nbsp; &nbsp; </button>&nbsp; &nbsp; </div>&nbsp; );};
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript