React useEffect 警告 Warning: Can't perform a React state update on an unmounted component
React useEffect Warning Warning: Can't perform a React state update on an unmounted component
这个组件有问题。
当我不断调用这个组件时,我收到了一条警告消息。
警告信息如下所示。
Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.
我已经使用 return 方法清除了 timerId 但我得到了这个文本。
如何修改这个组件中的useEffect?
我该怎么办?
下面是我的组件
import React, { useState, useEffect } from 'react';
import { Form, List, Button } from 'semantic-ui-react';
import axios from 'axios';
const Search = () => {
const [term, setTerm] = useState('programming')
const [debouncedTerm, setDebouncedTerm] = useState(term);
const [results, setResults] = useState([]);
useEffect(() => {
const timerId = setTimeout(() => {
setDebouncedTerm(term);
}, 1000);
return () => {
clearTimeout(timerId);
};
}, [term]);
useEffect(() => {
const search = async () => {
const {data} = await axios.get('https://en.wikipedia.org/w/api.php', {
params: {
action: 'query',
list: 'search',
origin: '*',
format: 'json',
srsearch: debouncedTerm,
},
});
setResults(data.query.search);
};
if(debouncedTerm){
search();
}
}, [debouncedTerm])
const handleClick = (pageid) => {
window.open(`https://en.wikipedia.org?curid=${pageid}`);
}
const renderedResults = results.map((result) => {
return (
<List.Item key={result.pageid}>
<Button floated='right' style={{"margin": "10px"}} onClick={() => handleClick(result.pageid)}>Go</Button>
<List.Content>
<List.Header>{result.title}</List.Header>
{result.snippet}
</List.Content>
</List.Item>
);
});
return (
<React.Fragment>
<Form>
<Form.Field>
<label>Search</label>
<input placeholder='Search Word'
onChange={(e) => setTerm(e.target.value)}
value={term}
/>
</Form.Field>
</Form>
<List celled>
{renderedResults}
</List>
</React.Fragment>
)
}
export default Search;
试试这个 (axios v0.22.0+):
useEffect(() => {
const controller= new AbortController();
const search = async () => {
try{
const {data} = await axios.get('https://en.wikipedia.org/w/api.php', {
params: {
action: 'query',
list: 'search',
origin: '*',
format: 'json',
srsearch: debouncedTerm,
},
signal: controller.signal
});
setResults(data.query.search);
}catch(err){
if (!axios.isCancel(err)) throw err;
}
};
if(debouncedTerm){
search();
}
return ()=>{
controller.abort();
}
}, [debouncedTerm])
同样的事情,但具有自动清理功能,可以使用我的库 (Generic fetch demo):
import { useAsyncEffect } from "use-async-effect2";
import cpAxios from "cp-axios";
// ...
useAsyncEffect(function*(){
if(!debouncedTerm){
return;
}
const {data} = yield cpAxios.get('https://en.wikipedia.org/w/api.php', {
params: {
action: 'query',
list: 'search',
origin: '*',
format: 'json',
srsearch: debouncedTerm,
}
});
setResults(data.query.search);
}, [debouncedTerm])
这可以简化为:
import { useAsyncEffect } from "use-async-effect2";
import cpAxios from "cp-axios";
// ...
const [cancel, done, results, err]= useAsyncEffect(function*(){
if(!debouncedTerm){
return;
}
const {data} = yield cpAxios.get('https://en.wikipedia.org/w/api.php', {
params: {
action: 'query',
list: 'search',
origin: '*',
format: 'json',
srsearch: debouncedTerm,
}
});
return data.query.search;
}, { states: true, deps: [debouncedTerm] });
console.log('results state:', results);
这个组件有问题。
当我不断调用这个组件时,我收到了一条警告消息。
警告信息如下所示。
Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.
我已经使用 return 方法清除了 timerId 但我得到了这个文本。
如何修改这个组件中的useEffect?
我该怎么办?
下面是我的组件
import React, { useState, useEffect } from 'react';
import { Form, List, Button } from 'semantic-ui-react';
import axios from 'axios';
const Search = () => {
const [term, setTerm] = useState('programming')
const [debouncedTerm, setDebouncedTerm] = useState(term);
const [results, setResults] = useState([]);
useEffect(() => {
const timerId = setTimeout(() => {
setDebouncedTerm(term);
}, 1000);
return () => {
clearTimeout(timerId);
};
}, [term]);
useEffect(() => {
const search = async () => {
const {data} = await axios.get('https://en.wikipedia.org/w/api.php', {
params: {
action: 'query',
list: 'search',
origin: '*',
format: 'json',
srsearch: debouncedTerm,
},
});
setResults(data.query.search);
};
if(debouncedTerm){
search();
}
}, [debouncedTerm])
const handleClick = (pageid) => {
window.open(`https://en.wikipedia.org?curid=${pageid}`);
}
const renderedResults = results.map((result) => {
return (
<List.Item key={result.pageid}>
<Button floated='right' style={{"margin": "10px"}} onClick={() => handleClick(result.pageid)}>Go</Button>
<List.Content>
<List.Header>{result.title}</List.Header>
{result.snippet}
</List.Content>
</List.Item>
);
});
return (
<React.Fragment>
<Form>
<Form.Field>
<label>Search</label>
<input placeholder='Search Word'
onChange={(e) => setTerm(e.target.value)}
value={term}
/>
</Form.Field>
</Form>
<List celled>
{renderedResults}
</List>
</React.Fragment>
)
}
export default Search;
试试这个 (axios v0.22.0+):
useEffect(() => {
const controller= new AbortController();
const search = async () => {
try{
const {data} = await axios.get('https://en.wikipedia.org/w/api.php', {
params: {
action: 'query',
list: 'search',
origin: '*',
format: 'json',
srsearch: debouncedTerm,
},
signal: controller.signal
});
setResults(data.query.search);
}catch(err){
if (!axios.isCancel(err)) throw err;
}
};
if(debouncedTerm){
search();
}
return ()=>{
controller.abort();
}
}, [debouncedTerm])
同样的事情,但具有自动清理功能,可以使用我的库 (Generic fetch demo):
import { useAsyncEffect } from "use-async-effect2";
import cpAxios from "cp-axios";
// ...
useAsyncEffect(function*(){
if(!debouncedTerm){
return;
}
const {data} = yield cpAxios.get('https://en.wikipedia.org/w/api.php', {
params: {
action: 'query',
list: 'search',
origin: '*',
format: 'json',
srsearch: debouncedTerm,
}
});
setResults(data.query.search);
}, [debouncedTerm])
这可以简化为:
import { useAsyncEffect } from "use-async-effect2";
import cpAxios from "cp-axios";
// ...
const [cancel, done, results, err]= useAsyncEffect(function*(){
if(!debouncedTerm){
return;
}
const {data} = yield cpAxios.get('https://en.wikipedia.org/w/api.php', {
params: {
action: 'query',
list: 'search',
origin: '*',
format: 'json',
srsearch: debouncedTerm,
}
});
return data.query.search;
}, { states: true, deps: [debouncedTerm] });
console.log('results state:', results);