javascript - react 钩子(Hook) : why does useEffect need an exhaustive array of dependencies?

标签 javascript reactjs typescript react-hooks

我在 React 组件中有以下用例。
这是一个使用 React Autosuggest 的搜索用户输入。 .它的值始终是一个 ID,所以我只有用户 ID 作为 Prop 。因此,在第一次加载以显示用户名值时,我需要在第一次安装时获取它。
编辑:我不想在以后更改时再次获取该值,因为我已经从我的建议请求中获得了该值。

type InputUserProps = {
  userID?: string;
  onChange: (userID: string) => void;
};

// Input User is a controlled input
const InputUser: React.FC<InputUserProps> = (props) => {
  const [username, setUsername] = useState<string | null>(null);

  useEffect(() => {
    if (props.userID && !username) {
      fetchUsername(props.userID).then((username) => setUsername(username));
    }
  }, []);

  async function loadSuggestions(inputValue: string): Suggestion[] {
    return fetchSuggestions(inputValue);
  }

  function selectSuggestion(suggestion: Suggestion): void {
    props.onChange(suggestion.userID); // I don't want to rerun the effect from that change...
    setUsername(suggestion.username); // ...because I set the username here
  }

  return (
    <InputSuggest
      value={props.userID}
      label={username}
      onSuggestionsRequested={loadSuggestions}
      onSuggestionSelected={selectSuggestion}
    />
  );
};

export default InputUser;
(我正在添加一个简化的方式来调用这个组件)
const App: React.FC<AppProps> = (props) => {
    // simplified, I use react-hook-form in the real code
    const [userID, setUserID] = useState<string?>(any_initial_value_or_null);
    return <InputUser userID={userID} onChange={(newValue)=>setUserID(newValue)} />
};

export default App;
它有效,但我的 useEffect 钩子(Hook)上有以下警告
React Hook useEffect has missing dependencies: 'props.userID' and 'username'. Either include them or remove the dependency array.eslint(react-hooks/exhaustive-deps)
但是如果我这样做,我会运行它不止一次,因为用户名值是由钩子(Hook)本身更改的!由于它在没有所有依赖项的情况下工作,我想知道:
  • 我怎样才能干净地解决我的案子?
  • 这些依赖项是什么?为什么建议对它们进行详尽的描述?
  • 最佳答案

    看起来像 userId确实应该是一个依赖项,因为如果它发生变化,你想再次运行你的查询。
    我认为您可以放弃对 username 的检查。并且总是在且仅当 userId变化:

    useEffect(() => {
        if(props.userID) {
            fetchUsername(props.userID)
                .then((username) => setUsername(username))
        }
    }, [props.userID])
    
    一般来说,您希望列出效果中的所有闭包变量,以避免执行效果时过时的引用。
    - 编辑以解决 OP 问题:
    因为在您的用例中,您知道您只想在初始挂载上执行操作,传递一个空的依赖数组是一种有效的方法。
    另一种选择是跟踪获取的用户 ID,例如
    const fetchedIds = useRef(new Set())
    
    每当您获取新 ID 的用户名时,您都可以更新引用:
    fetchedIds.current.add(newId)
    
    在您的效果中,您可以测试:
    if (props.userID && !fetchedIds.current.has(props.userID)) {
       // do the fetch
    }
    

    关于javascript - react 钩子(Hook) : why does useEffect need an exhaustive array of dependencies?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63216143/

    相关文章:

    javascript - React 语法不起作用

    javascript - typescript 错误 - 类型上不存在属性 'permission'

    javascript - 使用 JS 循环列表,同时与文本保持一致

    reactjs - React 中的延迟加载路由与 Typescript AsyncComponent

    javascript - 隐藏包含跨度的单元格的表行

    css - 如何使用 Jest 测试样式

    javascript - 如何从 TypeScript 文件生成类型定义文件?

    angular - 基于数组 Angular 2 中 id 数量的动态 URL 参数

    javascript - 引导模式中的引导日期选择器

    Javascript Regex - 如何提取图像路径之前的最后一个单词