小编Joj*_*oji的帖子

为什么每次渲染都会调用来自 `useEffect` 的清理函数?

我一直在学习 React,我读到从返回的函数useEffect是为了进行清理,而 React 在组件卸载时执行清理。

因此,我对其进行了一些试验,但在以下示例中发现,每次组件重新渲染时都会调用该函数,而不是仅在从 DOM 卸载时调用该函数,即每次组件重新渲染时都会调用该函数console.log("unmount");

这是为什么?

function Something({ setShow }) {
  const [array, setArray] = useState([]);
  const myRef = useRef(null);

  useEffect(() => {
    const id = setInterval(() => {
      setArray(array.concat("hello"));
    }, 3000);
    myRef.current = id;
    return () => {
      console.log("unmount");
      clearInterval(myRef.current);
    };
  }, [array]);

  const unmount = () => {
    setShow(false);
  };

  return (
    <div>
      {array.map((item, index) => {
        return (
          <p key={index}>
            {Array(index + 1)
              .fill(item)
              .join("")}
          </p>
        );
      })}
      <button onClick={() => …
Run Code Online (Sandbox Code Playgroud)

javascript reactjs react-hooks use-effect

40
推荐指数
1
解决办法
3万
查看次数

关于这个 React 自定义钩子用法的困惑

我正在看一些关于 React Hooks 的教程,在教程中作者创建了一个useDropdown用于渲染可重用下拉列表的钩子。代码是这样的

import React, { useState } from "react";

const useDropdown = (label, defaultState, options) => {
  const [state, updateState] = useState(defaultState);
  const id = `use-dropdown-${label.replace(" ", "").toLowerCase()}`;
  const Dropdown = () => (
    <label htmlFor={id}>
      {label}
      <select
        id={id}
        value={state}
        onChange={e => updateState(e.target.value)}
        onBlur={e => updateState(e.target.value)}
        disabled={!options.length}
      >
        <option />
        {options.map(item => (
          <option key={item} value={item}>
            {item}
          </option>
        ))}
      </select>
    </label>
  );
  return [state, Dropdown, updateState];
};

export default useDropdown;
Run Code Online (Sandbox Code Playgroud)

他在这样的组件中使用了它

import React, { useState, useEffect …
Run Code Online (Sandbox Code Playgroud)

javascript reactjs react-hooks

19
推荐指数
3
解决办法
3490
查看次数

关于使用 JavaScript 显示外部 url 图像的不同方式的困惑

我最近了解到似乎有多种方法可以在网页上显示图像。

第一种方法是直接将 URL 分配给图像元素的 URL

const img = new Image();

img.onload = () => {
  document.querySelector("#myImage").src = url;
};
img.onerror = () => {};

img.src = imageUrl;
Run Code Online (Sandbox Code Playgroud)

我最近学到的另一种方法是使用fetch

fetch(imageUrl)
    .then((response)=>response.blob())
    .then((blob)=>{
       const objectUrl = URL.createObjectURL(blob)
       document.querySelector("#myImage").src = objectUrl;
})
Run Code Online (Sandbox Code Playgroud)

我对这两种方法都有一些疑问:

  1. 我很熟悉,fetch但我通常用它来获取 JSON。在我看来,第二种获取fetch图像的方法就像我们通过 HTTP 获取该图像文件的原始二进制数据,而第一种方法是我们委托浏览器启动Get获取该图像的请求。但从服务器的角度来看,在如何发送图像方面没有区别?我这样理解对吗?

  2. 在什么情况下我们应该优先选择一种方法而不是另一种?我觉得第二种方法比第一种方法会出现很多 CORS 问题,但不确定具体原因。

  3. 还有其他方法可以在网页上显示图像吗?当人们谈论图像时,我经常听说 Base64 编码/解码。response.blob()base64与ie第二种方法有关吗?还是有所不同?如果是这样,有人可以给我一个使用 base64 显示图像的例子吗?

  4. 最后,我认为显示图像一直是我前端或 Web 开发知识中的一个漏洞。请随时推荐有关此主题的任何好的资源。

html javascript base64 fetch-api

14
推荐指数
2
解决办法
3451
查看次数

TypeScript:有没有办法将字符串文字类型转换为数字类型?

是否可以编写一个实用程序类型Number<T>,它接受可以转换为数字的字符串文字类型,如果不能,则返回一个never类型?

type Five = Number<'5'> // `Five` is of the type number 5
Run Code Online (Sandbox Code Playgroud)

我只是想先回答一下我为什么要这样做的问题:

我问这个问题的原因是我正在尝试编写一个Add实用程序类型来添加数字

type createArray<Len, Ele, Arr extends Ele[] = []> =  Arr['length'] extends Len ? Arr : createArray<Len, Ele, [Ele, ...Arr]>

type Add<A extends number, B extends number> = [...createArray<A, 1>, ...createArray<B, 1>]['length']
Run Code Online (Sandbox Code Playgroud)

现在它有效

type Five = Number<'5'> // `Five` is of the type number 5
Run Code Online (Sandbox Code Playgroud)

但它只接受number类型。我想让它也不接受string类型,这样它也可以工作type Answer = Add<'3','10'>

typescript

14
推荐指数
2
解决办法
3551
查看次数

TypeScript:为什么我的过滤方法无法缩小类型并消除数组中的 undefined 和 false

我从d.tsAPI 文件中得到了这种类型

type EventConfigurations = {
  Event1: {
    Enabled?: boolean;
  };

  Event2: {
    Enabled?: boolean;
  };

  Event3: {
    Enabled?: boolean;
  };
};
Run Code Online (Sandbox Code Playgroud)

现在我已经从该 API 调用的响应中返回了这些数据

const eventConfigurations: EventConfigurations = {
  Event1: { Enabled: true },

  Event2: { Enabled: false },

  Event3: { Enabled: true }
};
Run Code Online (Sandbox Code Playgroud)

现在我想将数据映射到


enum EventDesc {
  Event1 = "XXX",
  Event2 = "YYY",
  Event3 = "ZZZ"
}

type MyEvent = {
  eventDesc: EventDesc;
  topic: EventTopic;
};

const eventConfigurations: EventConfigurations = {
  Event1: { Enabled: true …
Run Code Online (Sandbox Code Playgroud)

javascript typescript

13
推荐指数
2
解决办法
6657
查看次数

React w/TypeScript:为什么当 useState 将回调作为更新程序时,状态的类型会丢失

首先,您将看到的代码片段是一个人为的示例。我只是好奇为什么打字不起作用。

interface MyState {
  a: boolean;
  b: number;
}

const defaultState: MyState = {
  a: false,
  b: 1
};

const keys = Object.keys(defaultState) as Array<keyof MyState>;

export default function App() {
  const [myState, setMyState] = React.useState<MyState>(defaultState);

  React.useEffect(() => {
    keys.forEach((key) => {
      setMyState((prev) => ({
        ...prev,
        [key]: "lol". // should've given an error but it didn't
      }));
    });
  }, []);

Run Code Online (Sandbox Code Playgroud)

所以我有一个defaultState和它在组件外部定义的键列表。在 useEffect 中,我使用密钥来更新状态(现在它只是将每个值更改为“lol”)。我传递了一个回调作为 中的更新程序,setMyState它返回的应该是新状态。但是在这里我将值设为字符串,这违反了我拥有的接口MyState

我想知道为什么它没有触发错误

这是一个现场演示:https : //codesandbox.io/s/sweet-dewdney-u83id?file=/ src/ App.tsx

没有反应的最小例子:游乐场

typescript reactjs

12
推荐指数
1
解决办法
209
查看次数

有关此代码段的执行顺序的问题

因此,最近我一直在阅读有关Javascript承诺的教程。

这是一个示例,用于解释宏任务队列(即事件循环)和微任务队列。

let promise = Promise.reject(new Error("Promise Failed!"));
promise.catch(err => alert('caught'));

// no error, all quiet
window.addEventListener('unhandledrejection', event => alert(event.reason));
Run Code Online (Sandbox Code Playgroud)

它说,因为promise.catch捕获错误,所以最后一行,所以事件处理程序永远不会运行。我能理解 但是随后他稍微调整了这个示例。

let promise = Promise.reject(new Error("Promise Failed!"));
setTimeout(() => promise.catch(err => alert('caught')));

// Error: Promise Failed!
window.addEventListener('unhandledrejection', event => alert(event.reason));
Run Code Online (Sandbox Code Playgroud)

这一次,他说,事件处理程序会首先运行,并捕获错误并经过这个promise.catch最终捕获错误。

对于第二个示例,我不了解的是,为什么事件处理程序在promise.catch?之前运行?

我的理解是

  1. 第一行,我们首先遇到一个承诺,然后将其放在微任务队列中。
  2. 第二行,我们有一个setTimeout,将其放在宏任务队列中,
  3. 第三行,我们有一个事件处理程序,并将该处理程序放在宏任务队列上等待被触发

然后,因为微任务比宏任务具有更高的优先级。我们首先兑现诺言。之后,我们将宏任务队列中的第一个任务出队setTimeout。因此,根据我的理解,该错误应由内部函数捕获setTimeout

请纠正我。

javascript event-loop

11
推荐指数
1
解决办法
157
查看次数

解析错误:关键字“enum”被保留

我正在用 React 编写 TypeScript。该项目是用 CRA 生成的。我使用react-app.eslintrc.json. 不过我决定使用,eslint-config-airbnb所以我添加了它并更改了我的.eslintrc.json

{
  "extends": [
    "airbnb",
  ]
}
Run Code Online (Sandbox Code Playgroud)

突然我从 ESLint 得到了关于enum我在代码库中使用的类型的解析错误

`Parsing error: The keyword 'enum' is reserved eslint`
Run Code Online (Sandbox Code Playgroud)

我用谷歌搜索但找不到答案。尝试添加一些额外的配置,例如

"parserOptions": {
    "ecmaVersion": 7,
  }
Run Code Online (Sandbox Code Playgroud)

但这并不能解决问题

typescript reactjs eslint eslint-config-airbnb typescript-eslint

10
推荐指数
1
解决办法
7625
查看次数

Babel/preset-env:关于设置用于传送 Polyfill 的目标环境的混乱

我正在学习如何使用@babel/preset-env我们的客户所需的浏览器polyfills。我的理解是,如果访问网站的客户端是目标环境之一,babel 就会发送polyfills。似乎有两种方法可以指定目标环境: 1. browserlist 2.targets选项{ "presets": [["@babel/preset-env", { "targets": "defaults" }]] }

但这里有几点我不太明白:

  1. 看起来 Polyfills 都来自core-js. 添加 polyfill 似乎是一个构建时过程。我不太明白的是 babel 实际上是如何选择客户端需要的 polyfills 的 - babel 是一次性导入所有的 polyfills 并且仅在需要时在运行时应用它还是仅在构建时导入所需的 polyfills?如果 Babel 没有选择要应用的 polyfill,那么在运行时会如何发生这种情况?有人可以向我详细解释一下吗?
  2. 使用选项targets设置目标环境与使用browserlist设置目标环境有什么区别此外,我对 的默认查询感到困惑targets。在 babel 的文档上它说

因此,preset-env 的行为与 browserslist 不同:当 Babel 或 browserslist 配置中没有找到目标时,它不会使用默认查询。如果您想使用默认查询,则需要显式地将其作为目标传递:

因此,仅拥有{ "presets": ["@babel/preset-env"] }不会给我们默认查询,我们必须显式地将目标设置为默认值,如"presets": [["@babel/preset-env", { "targets": "defaults" }]]

  1. 这与我的第二个问题有关 - 如果我有一个项目已经定义"@babel/preset-env"但没有browserlist …

javascript polyfills babeljs

10
推荐指数
1
解决办法
6335
查看次数

TypeScript + React:如何输入“rest”道具,将其余道具收集到一个对象中,然后将它们传播到某个元素?

function Foo({
  children,
  ...rest
}: {
  children: React.ReactNode;
  /*rest: how do I type `rest`? */
}) {
  return (
    <span style={{ background: "red" }} {...rest}>
      {children}
    </span>
  );
}

export default function App() {
  return (
    <div className="App">
      <Foo style={{ background: "blue" }}>Hello CodeSandbox</Foo>
    </div>
  );
}
Run Code Online (Sandbox Code Playgroud)

这是演示:https://codesandbox.io/s/how-to-type-rest-huv2z? file=/src/App.tsx:50-412

Foo用于覆盖span接受的 props。我该如何rest输入Foo

javascript typescript reactjs

10
推荐指数
2
解决办法
6663
查看次数