09-09-2021
使用时在component中需把useEffect
从react
函式库中引入
import { useEffect } from 'react';
若需要与其他的变数联合起来需要需要写成:
import React, { useState, useEffect } from 'react';
我们的effect在function component渲染後被调用,但仍然可以使用function component中的变数。
当React 渲染function component後,会一样的更新DOM,然後在DOM更新後运行我们的效果。
import React, { useState, useEffect } from 'react';
export default function Counter() {
const [count, setCount] = useState(0);
useEffect(() => {
alert(`Count: ${count}`);
});
const handleClick = () => {
setCount((prevCount) => prevCount + 1);
};
return (
<div>
<p>You clicked {count} times</p>
<button onClick={handleClick}>
Click me
</button>
</div>
);
}
一定要在调用State Hook之後使用Effect Hook,这样我们才能使用到count变数和之前的handleClick()函数。
useEffect(() => {
alert(`Count: ${count}`);
});
使用useEffect()
调用
alert()使用(Template literals)反引号(back-tick)将显示的变数写在里面
若没有将effect
return clean up ,那每次document 在component 重新渲染时都会将一个新的事件监听气添加到DOM中,不仅会导致错误,也会让效能下降
effect()
都是在渲染之後执行,而且不是一次,是每次React 重新渲染时都会执行。所以我们在渲染之前和卸载之後使用clean up effect
清理每一个调用的效果若我们的effect retrun是一个function,那use effect() 就会把他当做是一个 cleanup function。 React 会在重新渲染之前或是卸载之後呼叫cleanup function 。
memory leak
所以要清除掉* memory leak
(记忆体管理)
当value在被宣告时同时也完成了记忆体的配置,且会自动释放不再使用的值。
回收的机制主要是「参考概念」,如果物件中会使用到另外一个物件,即是该物件参考另外一个物件。
JavaScript 中的proptotype以及该物件的属性,即是隐式参考(前者)以及显示参考(後者)
Reference-counting garbage collection
可以用「没有其他物件参考它」简言之,如果一个物件没有被其他物件参考,即可被视为可以被回收的记忆体垃圾。
// 范例
import React, { useState, useEffect } from 'react';
export default function Counter() {
const [clickCount, setClickCount] = useState(0);
const increment = () => setClickCount((prev) => prev + 1);
useEffect(() => {
document.addEventListener('mousedown', increment);
return () => {
document.removeEventListener('mousedown', increment);
};
});
return (
<h1>Document Clicks: {clickCount}</h1>
);
}
监听滑鼠按下的监听事件,cleanup function 是一个新的function内容在effect中return
useEffect(() => {
document.addEventListener('mousedown', increment);
return () => {
document.removeEventListener('mousedown', increment);
};
});
在定义function component时,使用effect 通常只有在component在mounts时候(renders 的第一次),而不是在re-render的时候,而Effect Hook 可以让我们达成这件事情。
如果我们想要在第一次渲染後调用effect,我们传递一个空的array给useEffect()作为第二个参数。
而这个第二个参数称为==依赖阵列(dependency array)==
依赖阵列告诉useEffect()何时该调用effect何时该跳过它。
effect 总是会在第一次渲染後调用 ; 但只有在依赖阵列中的某些内容渲染间更改了value才会再次调用
// 范例
useEffect(() => {
document.title = `You clicked ${count} times`;
}, [count]); // 只会在count的值发生变化时再次调用
当component 渲染的数据没有变化时,我们可以传递一个空的阵列(依赖阵列),在第一次渲染後获得数据,当收到来自服务器的响应时,我们可以使用 State Hook 中的setState()将来自服务器响应的数据储存在我们本地组件状态中以供渲染。这种方式一起使用 State Hook 和 Effect Hook,可以避免我们的component在每次渲染後不必要地获取新数据!
一个非空的依赖阵列向 Effect Hook 发出请求时,它可以在重新渲染後跳过调用我们的效果,除非我们的依赖阵列中的一个变数的value发生了变化。如果依赖项的值发生了变化,那麽 Effect Hook 会再次调用我们的 effect!
import React, { useState, useEffect } from 'react';
import { get } from './Backend/fetch';
export default function Forecast() {
const [data, setData] = useState(null);
const [file, setFile] = useState({});
const [fileList, setFileList] = useState('/korea');
useEffect(() => {
alert('资料来了···');
get(fileList).then((response) => {
alert('Response: ' + JSON.stringify(response,'',2));
setData(response.data);
});
}, [fileList]);
const handleChange = (itemId) => ({ target }) =>
setFile((prev) => ({
...prev,
[itemId]: target.value
}));
if (!data) {
return <p>Loading...</p>;
}
return (
<div className='App'>
<h1>影片区</h1>
<div>
<button onClick={() => setFileList('/korea')}>韩剧馆</button>
<button onClick={() => setFileList('/japan')}>日剧馆</button>
</div>
</div>
);
}
使用 if
在没有接到数据时渲染出Loading..
if (!data) {
return <p>Loading...</p>;
}
将接到的数据存在setData()之中
使用useEffect的第二个参数,一个空的阵列,确保我们的component 在第一次渲染之後才拿到数据
useEffect(() => {
alert('资料来了···');
get(fileList).then((response) => {
alert('Response: ' + JSON.stringify(response,'',2));
setData(response.data);
});
}, [fileList]);
将fetch 的api 整理成独立一份文件,使用get
变数引入
在方法中使用变数forecastType
的值来确定要去调用哪个端点的资料,如此只要值有改变就会决定要去调用哪一个端点/korea \ /japan
import { get } from './Backend/fetch';
useEffect(() => {
alert('资料来了···');
get(fileList).then((response) => {
alert('Response: ' + JSON.stringify(response,'',2));
setData(response.data);
});
}, [fileList]);
//
return
button onClick={() => setFileList('/korea')}>韩剧馆</button>
错误示范:
if (userName !== '') {
useEffect(() => {
localStorage.setItem('savedUserName', userName);
});
}
正确示范
useEffect(() => {
if (userName !== '') {
localStorage.setItem('savedUserName', userName);
}
});
将数据分门管理取代只有一个data下的使用方式,由於众多资料都归在同一个data上,不仅会造成阅读上的障碍,也使得使用effect上充满冲突,将data内使用到的项目分门别类的设置 useState()管理,再将从data中取得的资料储存到setState
以供後续提用。
import React, { useState, useEffect } from 'react';
import { get } from './mockBackend/fetch';
export default function SocialNetwork() {
const [menu, setMenu] = useState(null);
useEffect(() => {
get('/menu').then((response) => {
setMenu(response.data);
});
}, []);
// 更多其他引入的data省略..
return (
<div className='App'>
<h1>My Network</h1>
{!menu ? (
<p>Loading..</p>
) : (
<nav>
{menu.map((menuItem) => (
<button key={menuItem}>{menuItem}</button>
))}
</nav>
)}
// 更多资料呈现省略..
</div>
);
}
在这里使用了三元方程序判别接取到data的情境,以及使用menu做.map的方式将资料捞出显示。
{!menu ? (
<p>Loading..</p>
) : (
<nav>
{menu.map((menuItem) => (
<button key={menuItem}>{menuItem}</button>
))}
</nav>
)}
if 当条件成立的时候会执行 if 陈述式里的程序,而不成立时则执行另外一个陈述式。if 单从字面上...
FormTagHelper : 为.net对html原生的封装, 预设若没指定method则是采用g...
经过昨天的内容,读者们应该对於网页的渲染流程有大致的理解了。 我们再小小复习一下,大致上网页的渲染...
基本上网页与HTML、CSS、JavaScript息息相关, 虽然有办法、但很难去完整地分别拆开来讲...
本文将继上篇 【Lab】建构三层式云端架构(上),实作下半部分的内容,包含档案控管、RDS/EC2...