Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/375.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/24.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
Javascript 我能';t在条件呈现时使useEffect读取输入正确_Javascript_Reactjs_React Hooks - Fatal编程技术网

Javascript 我能';t在条件呈现时使useEffect读取输入正确

Javascript 我能';t在条件呈现时使useEffect读取输入正确,javascript,reactjs,react-hooks,Javascript,Reactjs,React Hooks,我正在尝试创建一个具有“静态”模式的输入组件。在此模式下,输入将被包含输入值的范围替换。在这个问题中,我使用范围输入 import React from 'react'; import ReactDOM from 'react-dom'; const { useState, useEffect, } = React; const RangeInput = ({ inputID, min, max, defaultValue, children, }) => { const [v

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

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')
);

不知何故,我的
useffect
返回函数在实际卸载后无法正确读取输入。我认为在
useffect
中使用return函数会导致函数在组件卸载之前运行。我做错了什么?

当然,如果
元素没有装入,您就不能访问
document.getElementById(inputID).value
,因为它不存在!即使是这样,你也不想这样解读它的价值。这是一种非常不负责任的做事方式。React组件应该在状态和道具中拥有它们所需要的一切——如果您发现自己直接查询或处理DOM,那么您(几乎总是)会走上一条黑暗的道路

相反,你想要的是一个

受控组件不依赖DOM来存储任何类似“值”的内容。相反,组件只显示React在状态中具有的任何值,并提供一个方便的事件挂钩

我强烈建议你阅读我链接的文档,看看你是否能自己想出一个实现方案。这毕竟是最好的学习方式!但如果你仍然无法理解,我会回来用一个基本的工作示例编辑我的答案

编辑:这里是一个简单的工作演示与一些意见


请注意,它实际上非常简单!
跟踪处于状态的滑块值,而
仅将该值作为道具使用,并提供一个事件处理程序,用于将其更新回
<代码>可以跟踪它自己的“编辑模式”值,因为其他组件可能不需要访问它(但如果需要,您可以将该状态“提升”到一个级别!)您甚至不需要
useffect()

当然,如果
元素未装入-它不存在,则无法访问
document.getElementById(inputID).value
!即使是这样,你也不想这样解读它的价值。这是一种非常不负责任的做事方式。React组件应该在状态和道具中拥有它们所需要的一切——如果您发现自己直接查询或处理DOM,那么您(几乎总是)会走上一条黑暗的道路

相反,你想要的是一个

受控组件不依赖DOM来存储任何类似“值”的内容。相反,组件只显示React在状态中具有的任何值,并提供一个方便的事件挂钩

我强烈建议你阅读我链接的文档,看看你是否能自己想出一个实现方案。这毕竟是最好的学习方式!但如果你仍然无法理解,我会回来用一个基本的工作示例编辑我的答案

编辑:这里是一个简单的工作演示与一些意见


请注意,它实际上非常简单!
跟踪处于状态的滑块值,而
仅将该值作为道具使用,并提供一个事件处理程序,用于将其更新回
<代码>可以跟踪它自己的“编辑模式”值,因为其他组件可能不需要访问它(但如果需要,您可以将该状态“提升”到一个级别!)您甚至不需要
useffect()

除非在卸载时有理由获取该值,否则您似乎可以在值发生变化时跟踪该值。这样,您根本不需要
useffect

const RangeInput = ({ inputID, min, max, defaultValue, children }) => {
  const [value, setValue] = useState(defaultValue); // <-- keep track of value
  const [isStatic, setIsStatic] = useState(false);

  return (
    <div>
      <label htmlFor={inputID}>{children}</label>
      {isStatic ? (
        <span>{value}</span>
      ) : (
        <input
          type="range"
          min={min}
          max={max}
          defaultValue={value}
          onChange={e => setValue(e.target.value)} // <-- Set value onChange
          id={inputID}
        />
      )}
      <button
        onClick={() => {
          setIsStatic(!isStatic);
        }}
      >
        Toggle Static
      </button>
    </div>
  );
};
const RangeInput=({inputID,min,max,defaultValue,children})=>{
const[value,setValue]=useState(defaultValue);//
切换静态
);
};

除非在卸载时有理由获取该值,否则您似乎可以在值更改时跟踪该值。这样,您根本不需要
useffect

const RangeInput = ({ inputID, min, max, defaultValue, children }) => {
  const [value, setValue] = useState(defaultValue); // <-- keep track of value
  const [isStatic, setIsStatic] = useState(false);

  return (
    <div>
      <label htmlFor={inputID}>{children}</label>
      {isStatic ? (
        <span>{value}</span>
      ) : (
        <input
          type="range"
          min={min}
          max={max}
          defaultValue={value}
          onChange={e => setValue(e.target.value)} // <-- Set value onChange
          id={inputID}
        />
      )}
      <button
        onClick={() => {
          setIsStatic(!isStatic);
        }}
      >
        Toggle Static
      </button>
    </div>
  );
};
const RangeInput=({inputID,min,max,defaultValue,children})=>{
const[value,setValue]=useState(defaultValue);//
切换静态
);
};

我喜欢临时维护状态的想法。切换按钮当然是出于测试目的,我的团队将使用Redux来维护状态。考虑到这一点,再看看@helloitsjoe的答案,使用这种方法,而不是像答案那样将逻辑保留在组件中,还有什么好处吗?这实际上不是一个HOC。但无论如何,这是有利的,因为当你考虑它时,
应该尽可能地“愚蠢”。如何读取滑块的值?它的价值必须在某个更高的层次上进行跟踪。如果您使用的是redux,那么如何将redux存储值连接到滑块?如果你的整个应用程序中只有一个滑块,那么直接连接就可以了。但是如果你有10个呢?20? 100? 你会怎么做,有100个不同的滑块组件,每个组件分别连接到redux?不,只是将值作为道具传递进来……我喜欢HOC维护状态的想法。切换按钮当然是出于测试目的,我的团队将使用Redux来维护状态。考虑到这一点,再看看@helloitsjoe的答案,使用这种方法,而不是像答案那样将逻辑保留在组件中,还有什么好处吗?这实际上不是一个HOC。但无论如何,这是有利的,因为当你考虑它时,
应该尽可能地“愚蠢”。如何读取滑块的值?它的价值必须在某个更高的层次上进行跟踪。如果您使用的是redux,那么如何将redux存储值连接到滑块?如果你的整个应用程序中只有一个滑块,那么直接连接就可以了。但是如果你有10个呢?20? 100? 你要做什么,吃10块