标签: use-effect

乐观渲染 & useEffect

TL'DR:有没有办法在对 API 调用使用 useEffect 时悲观地操作状态更改?

假设您编写了一个显示分页/排序数据网格的组件,并且您为该组件编写了一个 useEffect 类似于这个假示例:

useEffect(() => {
  fetch(`https://some-random-api.com/data/page/{paging}/sort/{sorting}`)
    .then(response => response.json())
    .then(data => setState({
      data
    }));
}, [paging, sorting]);
Run Code Online (Sandbox Code Playgroud)

所以,如果我没记错的话,这将在分页或排序状态/道具(whatev)更新时获取。这意味着它在加载数据之前乐观地呈现新的排序和分页状态。基本上,该应用程序会告诉用户“我在请求的页面上,但我仍在加载它”。换句话说,应用程序状态的一部分(分页和排序)表示“我完成了”,状态的另一部分(加载)表示“我正在处理它”。

相比之下,如果我悲观地更新状态,我只会在获取之前将加载状态设置为 true,然后在收到响应时(并且仅在那时)设置分页、排序(& 数据和加载)。因此,该应用程序会告诉用户“我听到了您的意见,我正在处理它”,然后当收到成功响应时,该应用程序会说“这是请求的数据和更新的上下文(更新的页面/排序状态)”。

另一个问题是请求是否失败。在 optimisitic/useEffect 方法中,我现在需要恢复在尝试加载这些状态更改的数据之前更新的分页和排序状态。这种复杂性随着依赖项的数量而增加。另外,这里是关键(再次,如果我没记错的话)恢复这些状态将导致另一个获取(这可能会再次失败)。在悲观方法中,您只需在发生错误时设置 loading = false 并且不会进行其他状态更改,因为分页和排序仅在成功接收数据时更新。数据以悲观的方式(不乐观)保持同步,这就是为什么我认为当博客和视频在使用 useEffect 时说“从同步的角度思考”是具有讽刺意味的。

还有一件事,比如说从 useEffect 内部调用的 API(在其他一些例子中)实际上正在改变服务器端的某些东西。在这种情况下,当使用 useEffect 并应用它的乐观方法时,只会对用户撒谎。该应用程序说“好的,我更新了”。也许不吧。如果没有(如果有错误),希望有状态更新来恢复对用户撒谎的状态更改,并在恢复该状态时以某种方式避免额外的 API 调用。希望用户看到状态变回并希望有一条消息......即便如此,这是一个好的用户体验吗?

我并不是说乐观渲染总是不好的。我的意思是“我大部分时间都喜欢悲观。我如何在使用 useEffect 时做到这一点?” :)

似乎 useEffect 正在被用于和推广应用程序的大多数副作用(很多)。我并不经常发现它很有用。我是一个悲观主义者,希望获得替代方案。

reactjs react-hooks use-effect

5
推荐指数
1
解决办法
894
查看次数

React Hooks:在 useEffects 中将对象作为依赖处理

更新:对于用例 1,是的,如果我在 useEffect 之外提取 search.value 并将其用作依赖项,则它可以工作。

但我在下面有一个更新的用例

用例 2:我想将 searchHits 对象传递给服务器。服务器反过来将其返回给我,并带有更新的值作为响应。如果我尝试使用 searchHits 对象,我仍然会得到无限循环

state: {
    visible: true,
    loading: false,
    search: {
        value: “”,
        searchHits: {....}, 
        highlight: false,
    }
}

let val = search.value
let hits = search.searchHits
useEffect( () => {

    axios.post(`/search=${state.search.value}`, {hits: hits}).then( resp => {
        …do something or ..do nothing
        state.setState( prevState => {
            return {
                …prevState,
                search: {... prevState.search, hits: resp.hit}
            }
        })
    })
}, [val, hits])

Run Code Online (Sandbox Code Playgroud)

用例 1:我想搜索一个字符串,然后在得到结果时突出显示

例如

state: {
    visible: true,
    loading: …
Run Code Online (Sandbox Code Playgroud)

javascript reactjs react-hooks use-effect

5
推荐指数
1
解决办法
6737
查看次数

在 useEffect 钩子中取消所有异步/等待任务以防止反应中的内存泄漏的正确方法是什么?

我正在开发一个从 firebase 数据库中提取数据的 react chap 应用程序。在我的“仪表板”组件中,我有一个 useEffect 钩子检查经过身份验证的用户,如果是,则从 firebase 中提取数据并设置电子邮件变量和聊天变量的状态。我使用 abortController 进行 useEffect 清理,但是每当我第一次注销并重新登录时,我都会收到内存泄漏警告。

index.js:1375 警告:无法对卸载的组件执行 React 状态更新。这是一个空操作,但它表明您的应用程序中存在内存泄漏。要修复,请取消 useEffect 清理函数中的所有订阅和异步任务。

在仪表板中(由 Context.Consumer 创建)

最初我没有 abortController,我只是在清理时返回了一个控制台日志。做了更多的研究,发现 abortController 但是这些例子使用了 fetch 和信号,我找不到任何与 async/await 一起使用的资源。我愿意更改数据的检索方式,(无论是使用 fetch、async/await 还是任何其他解决方案)我只是无法使用其他方法使其正常工作。

const [email, setEmail] = useState(null);
const [chats, setChats] = useState([]);

const signOut = () => {
    firebase.auth().signOut();
  };

useEffect(() => {
    const abortController = new AbortController();
    firebase.auth().onAuthStateChanged(async _user => {
      if (!_user) {
        history.push('/login');
      } else {
        await firebase
          .firestore()
          .collection('chats')
          .where('users', 'array-contains', _user.email)
          .onSnapshot(async res => …
Run Code Online (Sandbox Code Playgroud)

async-await firebase reactjs google-cloud-firestore use-effect

5
推荐指数
1
解决办法
2830
查看次数

用 useEffect 钩子替换 react 钩子中的 setState 回调,用于复杂的场景不起作用

嗨,我有一个场景,我需要在特定场景中使用 React_hooks 在反应钩子中设置新状态后替换 setState 回调。

当前代码是::

const ThemeOptions = () => {
  const [previewType, setPreviewType] = useState("Desktop");
  const [previewUrl, setPreviewUrl] = useState("");
  const [layout, setLayout] = useState(null);
  const [saving, setSaving] = useState(false);

  const handleSave = (newdata) => {
    setLayout(newdata);
    setSaving(true);

    axios
      .put(window.urls.save, this.state.layout)
      .then(
        function(response) { // i want this to change in hooks
           this.setState(
             {
               layout: response.data,
               saving: false,
             },
             function() {
               this.refs["preview"].refresh();
             }
           );
        }.bind(this)
      )
      .catch(
        function(error) {
          console.log(error);
          setSaving(false);
        }.bind(this)
      );
  }

  return (
    <div>
      <Router> …
Run Code Online (Sandbox Code Playgroud)

javascript setstate reactjs react-hooks use-effect

5
推荐指数
1
解决办法
2216
查看次数

React Promise异步任务顺序不正确

我正在使用 Promise 进行多次调用。

我要获取的 API 端点是:

  1. https://www.api-football.com/demo/v2/statistics/357/5/2019-08-30
  2. https://www.api-football.com/demo/v2/statistics/357/5/2019-09-30
  3. https://www.api-football.com/demo/v2/statistics/357/5/2019-10-30

看代码

export function getTeamsStats(league, team, type) {
  return function(dispatch) {

    const url = "https://www.api-football.com/demo/v2/statistics";
    let dates = ["2019-08-30", "2019-09-30", "2019-10-30"];
    const getAllData = (dates, i) => {
      return Promise.allSettled(dates.map(x => url + '/' + 357 + '/' + 5 + '/' + x).map(fetchData));
    }

    const fetchData = (URL) => {
      return axios
        .get(URL)
        .then(res => {
          const {
            matchsPlayed: { total: teamsTotalMatchsPlayed},
          } = res.data.api.statistics.matchs;

          const matchsPlayed = teamsTotalMatchsPlayed;

          dispatch(receivedTeamsStat(matchsPlayed, type)); …
Run Code Online (Sandbox Code Playgroud)

javascript promise reactjs react-hooks use-effect

5
推荐指数
1
解决办法
364
查看次数

无法使用 useState React 将道具设置为状态

我是新来的反应。我已经阅读了 React 文档。我不知道为什么它不起作用。所以,我来到这里。

我正在尝试在反应中创建分页。下面是我的table组件。

const Table = (props) => {
  const { description, itemCount, tableHeaders, items } = props;

  const pageSize = 5;
  const [currentPage, setCurrentPage] = useState(1);

  function handlePageChange(page) {
    setCurrentPage(page);
  }

  const registerations = paginate(items, currentPage, pageSize);
  // HERE: registerations data is correct and then I pass it to TableBody component.

  return (
    <React.Fragment>
      <TableDescription description={description} count={itemCount} />
      <div className="bg-white block w-full md:table">
        <TableHeader items={tableHeaders} />
        <TableBody items={registerations} />
      </div>
      {/* Footer & Pagination */}
      <div …
Run Code Online (Sandbox Code Playgroud)

javascript reactjs react-hooks use-effect use-state

5
推荐指数
1
解决办法
1969
查看次数

在 useEffect 中使用 useState 值而不进行状态更新 useEffect

我正在研究一个基于对象键管理字符串数组的函数。假设它看起来像这样:

import React, { useState, useEffect } from "react";
import FieldContext from "../contexts/FieldContext";
import io from "socket.io-client";

const [socket, setSocket] = useState(null);
// the `data` array gets changed every second due to a WebSocket, in case that's important
const [data, setData] = useState({ foo: [], bar: [] });
const [connections, setConnections] = useState(["conn1", "conn2"]);

const { checkedFields } = useContext(FieldContext); // ["foo", "moo"];

useEffect(() => {
  setConnections(prevConnections => {
    // The code below does the following: 
    // Loop through the …
Run Code Online (Sandbox Code Playgroud)

reactjs react-hooks use-effect use-state

5
推荐指数
1
解决办法
808
查看次数

“useEffect 缺少依赖项”警告有时会出错吗?

我已经使用 hooks 一段时间了,但我从来没有完全理解为什么 React 强迫我在 useEffect 上包含一些我不想要的依赖项。

\n

我理解 useEffect 挂钩的“依赖关系”的方式

\n

添加您想要在更改时“监听”的值并触发您的效果。这与简单的效果完美配合,例如:

\n
import React, {useEffect, useState} from "react";\n\ninterface Props {\n\xc2\xa0 \xc2\xa0 id: string\n}\n\nconst SimpleComponent = (props: Props) => {\n\xc2\xa0 \xc2\xa0 const {id} = props;\n\xc2\xa0 \xc2\xa0 const [response, setResponse] = useState<object>();\n\xc2\xa0 \xc2\xa0 \n\xc2\xa0 \xc2\xa0 useEffect(() => {\n\xc2\xa0 \xc2\xa0 \xc2\xa0 \xc2\xa0 fetch(`https://myexample/${id}`)\n\xc2\xa0 \xc2\xa0 \xc2\xa0 \xc2\xa0 \xc2\xa0 \xc2\xa0 .then(response => setResponse(response))\n\xc2\xa0 \xc2\xa0 \xc2\xa0 \xc2\xa0 \xc2\xa0 \xc2\xa0 .catch(() => console.log("An error occurs!"))\n\xc2\xa0 \xc2\xa0 }, [id])\n\xc2\xa0 \xc2\xa0 \n\xc2\xa0 \xc2\xa0 return <div/>\n};\n
Run Code Online (Sandbox Code Playgroud)\n

然而,还有一些其他情况并不像上面的例子那么简单。在这个例子中我们希望仅当 …

javascript reactjs react-hooks use-effect

5
推荐指数
1
解决办法
927
查看次数

如何在useEffect中使用setTimeout重置React钩子状态

我有一个简单的组件,可以将链接复制到剪贴板,并且想用复选标记交换链接图标。我有这样做的逻辑设置,但是在 3 秒后重置状态以将按钮重置回链接图标时遇到问题。如何正确设置我的useEffect和状态钩子以设置然后重置状态以显示/隐藏选中标记的链接并再次返回?

const [copySuccess, setCopySuccess] = useState('');
const [visible, setVisible] = useState(true);
const copyToClipBoard = async copyHeader => {
try {
  await navigator.clipboard.writeText(copyHeader);
    setCopySuccess('Copied!');
  } catch (err) {
    setCopySuccess('Failed to copy!');
  }
};

<Button>
    {copySuccess ? (
       <Icon name="success" />
    ):(
     <Icon
        name="linked"
        onClick={() => copyToClipBoard(url)}
     />
    )}
</Button>
Run Code Online (Sandbox Code Playgroud)

我正在尝试useEffect这样的:

useEffect(() => {
    setTimeout(() => {
      setVisible(false);
    }, 3000);
 });
  
Run Code Online (Sandbox Code Playgroud)

但不确定如何使用setVisible状态和超时,将图标交换回链接,让用户知道他们可以再次复制它。

reactjs react-hooks use-effect use-state

5
推荐指数
1
解决办法
253
查看次数

阅读布局时,`useLayoutEffect` 比`useEffect` 更可取吗?

useLayoutEffectvs 的一个不同之useEffect处在于useLayoutEffect它将在 DOM 突变之后和浏览器绘制阶段之前同步触发。(参考

但是,我遇到了一些文章,它们似乎都建议useLayoutEffect用于阅读布局。

反应文档:

签名与 useEffect 相同,但在所有 DOM 突变后同步触发。使用它从 DOM 读取布局并同步重新渲染。在浏览器有机会绘制之前, useLayoutEffect 内计划的更新将同步刷新。

肯特·C·多兹

useLayoutEffect:如果您需要改变 DOM 和/或确实需要执行测量

奥汉斯·伊曼纽尔:

在可能的情况下,如果您希望在浏览器绘制过程中不显眼,请选择 useEffect Hook。在现实世界中,这通常是大多数时候!好吧,除非你从 DOM 读取布局或者做一些需要尽快绘制的与 DOM 相关的事情。

据我了解,在useEffect触发时,浏览器已经通过了布局和绘制阶段,因此读取布局useEffect应该完全没问题。

所以我的问题是:阅读布局时useLayoutEffect更可取useEffect,如果是,为什么?考虑到我只是阅读了布局,并没有在效果中执行任何额外的状态更改。

reactjs react-hooks use-effect

5
推荐指数
1
解决办法
479
查看次数