猿问

我无法在条件渲染上正确使用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返回函数在它实际卸载时不会正确读取输入。我认为使用return函数useEffect会导致函数在组件卸载之前运行。我究竟做错了什么?


蝴蝶不菲
浏览 1338回答 2
2回答

汪汪一只猫

除非在卸载时有理由获得该值,否则您可能只是在更改时跟踪该值。那样你根本不需要useEffect:const&nbsp;RangeInput&nbsp;=&nbsp;({&nbsp;inputID,&nbsp;min,&nbsp;max,&nbsp;defaultValue,&nbsp;children&nbsp;})&nbsp;=>&nbsp;{ &nbsp;&nbsp;const&nbsp;[value,&nbsp;setValue]&nbsp;=&nbsp;useState(defaultValue);&nbsp;//&nbsp;<--&nbsp;keep&nbsp;track&nbsp;of&nbsp;value &nbsp;&nbsp;const&nbsp;[isStatic,&nbsp;setIsStatic]&nbsp;=&nbsp;useState(false); &nbsp;&nbsp;return&nbsp;( &nbsp;&nbsp;&nbsp;&nbsp;<div> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<label&nbsp;htmlFor={inputID}>{children}</label> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{isStatic&nbsp;?&nbsp;( &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>{value}</span> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;)&nbsp;:&nbsp;( &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<input &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;type="range" &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;min={min} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;max={max} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;defaultValue={value} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;onChange={e&nbsp;=>&nbsp;setValue(e.target.value)}&nbsp;//&nbsp;<--&nbsp;Set&nbsp;value&nbsp;onChange &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;id={inputID} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;)} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<button &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;onClick={()&nbsp;=>&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setIsStatic(!isStatic); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Toggle&nbsp;Static &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</button> &nbsp;&nbsp;&nbsp;&nbsp;</div> &nbsp;&nbsp;);};
随时随地看视频慕课网APP

相关分类

JavaScript
我要回答