React useEffect - 为什么闭包对象中的 属性 没有更新?
React useEffect - Why property from closure object does't get updated?
在下面的示例中,为什么从 obj
获取的函数没有更新我在 useEffect
中设置的新函数?
import React, {useEffect} from 'react';
function Example () {
const obj = {
fetch: () => {
throw 'Not implemented!';
}
}
useEffect(() => {
obj.fetch = async () => {
const data = await fetch('https://my.url.com');
console.log('Data:', data);
};
obj.fetch();
}, []);
return (
// the button click is throwing "Not implemented"
<button onClick={() => obj.fetch()}>Test</button>
);
}
如果按钮点击抛出 "Not implemented",这是因为 Example
在按钮点击之前 re-rendered。如果您使用下面我的代码的沙箱,您会发现只要您不单击 "Trigger render","Test" 按钮就会按预期工作。您的 useEffect
依赖项数组仅设置为在挂载时执行。 re-render 创建一个新的 obj
,它永远不会重新分配 fetch
函数。
import React, { useState, useEffect } from "react";
import ReactDOM from "react-dom";
function Example() {
const obj = {
fetch: () => {
console.error("Not implemented!");
}
};
useEffect(() => {
obj.fetch = async () => {
console.log("Implemented");
};
obj.fetch();
}, []);
return (
<button onClick={() => obj.fetch()}>Test</button>
);
}
function App() {
const [renderTrigger, setRenderTrigger] = useState(0);
return (
<>
<Example />
<br />
<button onClick={() => setRenderTrigger(prev => prev + 1)}>
Trigger render
</button>
<br />
{renderTrigger}
</>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
在下面的示例中,为什么从 obj
获取的函数没有更新我在 useEffect
中设置的新函数?
import React, {useEffect} from 'react';
function Example () {
const obj = {
fetch: () => {
throw 'Not implemented!';
}
}
useEffect(() => {
obj.fetch = async () => {
const data = await fetch('https://my.url.com');
console.log('Data:', data);
};
obj.fetch();
}, []);
return (
// the button click is throwing "Not implemented"
<button onClick={() => obj.fetch()}>Test</button>
);
}
如果按钮点击抛出 "Not implemented",这是因为 Example
在按钮点击之前 re-rendered。如果您使用下面我的代码的沙箱,您会发现只要您不单击 "Trigger render","Test" 按钮就会按预期工作。您的 useEffect
依赖项数组仅设置为在挂载时执行。 re-render 创建一个新的 obj
,它永远不会重新分配 fetch
函数。
import React, { useState, useEffect } from "react";
import ReactDOM from "react-dom";
function Example() {
const obj = {
fetch: () => {
console.error("Not implemented!");
}
};
useEffect(() => {
obj.fetch = async () => {
console.log("Implemented");
};
obj.fetch();
}, []);
return (
<button onClick={() => obj.fetch()}>Test</button>
);
}
function App() {
const [renderTrigger, setRenderTrigger] = useState(0);
return (
<>
<Example />
<br />
<button onClick={() => setRenderTrigger(prev => prev + 1)}>
Trigger render
</button>
<br />
{renderTrigger}
</>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);