简体   繁体   English

使用来自嵌套 componentDidMount() 的钩子

[英]Using hooks from a nested componentDidMount()

I am trying to integrate hooks with some legacy React code.我正在尝试将钩子与一些遗留的 React 代码集成。 My old react code triggers a callback from a componentDidMount.我的旧反应代码触发了来自 componentDidMount 的回调。 I wanted to use a hook in the callback to update some state, but that doesnt seem to work: the hook gets stuck with the original value.我想在回调中使用挂钩来更新一些 state,但这似乎不起作用:挂钩卡在原始值上。 Here's a pared down, reproducible example:这是一个精简的、可重现的示例:

https://jsfiddle.net/0yf2xm96/16/ https://jsfiddle.net/0yf2xm96/16/

const Test = () => {
    const [value, setValue] = React.useState(0);
  
    return (
    <div>
      <Test2 onMount={() => setValue(value + 1)} />
      <Test2 onMount={() => setValue(value + 1)} />

      { value /* displays 1, but I'd like to see 2 */ }
    </div>
  );
}

class Test2 extends React.Component {
    componentDidMount() {
    this.props.onMount();
  }
  
  render() { return null; }
}

ReactDOM.render(<Test />, document.querySelector("#app"))

I want that to display 2, not 1 - how would i go about doing that?我希望它显示 2,而不是 1 - 我将如何 go 这样做?

You can pass a function to the useState hook that takes the previous state value as an argument, as seen in the docs .您可以将 function 传递给useState挂钩,该挂钩将先前的 state 值作为参数,如docs中所示。 Change your onMount to:将您的 onMount 更改为:

<Test2 onMount={() => setValue(prev=>prev + 1)} />
<Test2 onMount={() => setValue(prev=>prev + 1)} />

Ciao, I suggest you to modify your code like this: Ciao,我建议你像这样修改你的代码:

const Test = () => {
    const [value, setValue] = React.useState(0);
  
  
    return (
    <div>
      <Test2 onMount={() => setValue(value => value + 1)} />
      <Test2 onMount={() => setValue(value => value + 1)} />

      { value }
    </div>
  );
}

Explanation: you know hook are async and if you call just setValue(value + 1) you are not considering the previous value of value .解释:你知道钩子是异步的,如果你只调用setValue(value + 1)你没有考虑 value 的前一个value Bu tif you use arrow funcition the problem will be solved.但是如果您使用箭头功能,问题将得到解决。

Here your code modified.在这里您的代码已修改。

TLDR: Value is "stale". TLDR:价值是“陈旧的”。 Use a functional update.使用功能更新。


What's causing the problem是什么导致了问题

Lets think about this in plain javascript terms first.让我们先用简单的 javascript 术语来考虑这个问题。

Test is a function. Test是 function。 Yes, its a component so it gets used like a special function with special JSX syntax, but ultimately its just a function.是的,它是一个组件,因此它被用作具有特殊 JSX 语法的特殊 function,但最终它只是一个 function。

With that understanding, we can also understand that value , while it is part of a useState hook, is just a javascript variable.有了这个理解,我们也可以理解value ,虽然它是useState钩子的一部分,但它只是一个 javascript 变量。 In fact, its a const which means its value cannot be changed after it has been declared.实际上,它是一个const ,这意味着它的值在声明后不能更改。 I think this is a misunderstanding that most people have about the useState hook - just because it's stateful does not mean it can abandon the rules of being a const .我认为这是大多数人对useState钩子的误解——仅仅因为它是有状态的并不意味着它可以放弃成为const的规则。

When you call a useState updater, it will signal React that the component needs to re-render.当你调用useState更新器时,它会向 React 发出组件需要重新渲染的信号。 This re-render may not happen immediately .这种重新渲染可能不会立即发生 When the component is re-rendered, the function Test is called again.重新渲染组件时,再次调用 function Test The implications of this are that a new const called value is created.这意味着创建了一个名为valueconst The new const is assigned the value passed from the useState updater.新的const被分配从useState更新程序传递的值。 This is what makes the hook so powerful.这就是钩子如此强大的原因。 Setting state is not a simple variable assignment, it is a way to maintain values through multiple function calls.设置 state 不是简单的变量赋值,它是一种通过多次 function 调用来维护值的方法。

Back to the issue: When you declare two arrow functions like you did here:回到问题:当你像这里一样声明两个箭头函数时:

<Test2 onMount={() => setValue(value + 1)} />
<Test2 onMount={() => setValue(value + 1)} />

You can hopefully now see that value in both of these functions is 0. Even after the first function is called, value is a const and still retains the value 0. Both functions get called before the next render cycle, which means the second one to be called is victim to value going stale.您现在可以希望看到这两个函数中的value都是 0。即使在第一个 function 被调用之后, value也是一个const并且仍然保留值 0。这两个函数在下一个渲染周期之前被调用,这意味着第二个被称为是value过时的受害者。

Solution解决方案

Use the callback version of setting state referred to as functional updates .使用回调版本设置 state 称为功能更新 Most people eventually figure out the solution whether they understand why or not.大多数人最终都会找到解决方案,无论他们是否理解原因 When using the updater form, the value of state passed into the callback function is always guaranteed to use the most recent version, thereby removing the issue.使用更新程序表单时,传递给回调 function 的 state 的值始终保证使用最新版本,从而消除了该问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 将 componentDidUpdate componentDidMount 转换为 hooks - converting componentDidUpdate componentDidMount to hooks React Hooks:在componentDidMount上调度一个动作 - React Hooks: Dispatch an action on componentDidMount 使用嵌套的钩子来更新状态 - Using nested hooks to update state 在 componentDidMount() 中使用 React.setState 来获取嵌套 promise 中返回的数据? - Using React.setState in componentDidMount() for data returned within nested promises? React 函数/Hooks 组件上的 componentDidMount 等价物? - componentDidMount equivalent on a React function/Hooks component? React:将重点放在 componentDidMount 上,如何使用钩子来实现? - React: set focus on componentDidMount, how to do it with hooks? 使用 React Hooks 时如何防止事件在嵌套的 div 中起作用 - How to prevent events from acting in nested divs when using React Hooks 使用 componentDidMount 和 componentWillRecieveProps 方法无法从父级获取道具 testHighlight - using componentDidMount and componentWillRecieveProps methods not able to fetch the props testHighlight from parent 我如何从`componentDidMount`(使用 Redux)获得 state? - How can I get the state from `componentDidMount `(using Redux)? 来自componentDidMount的错误请求 - Bad request from componentDidMount
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM