我正在使用套接字中的useEffect Hook获取数据。每次我得到响应时,一个特定的组件都会重新呈现,但是我没有将任何套接字数据传递给该组件。
码:
const App = () => {
const isMounted = React.useRef(false);
const [getSocketData, setSocketData] = useState([]);
useEffect(() => {
console.log('[App.js] Mounted!');
isMounted.current = true;
const socket = socketIOClient(process.env.REACT_APP_BOARD);
socket.on('ServersInfo', (data) => {
if (isMounted.current) {
setSocketData([...data]);
}
});
socket.on('connect_error', () => {
if (isMounted.current) {
setSocketData([]);
}
console.log('Connection error!');
});
return (() => {
isMounted.current = false;
socket.disconnect();
console.log('[App.js] unmounted');
});
}, []);
const routes = (
<Switch>
<Route path={['/', '/users/:id']} exact component={() => <MainPage axiosInstance={axiosInstance} />} />
<Route path='/servers' render={(spProps) => <ServerPing {...spProps} />} />
<Route render={(nfProps) => <NotFoundComponent {...nfProps} />} />
{/* <Redirect to='/' /> */}
</Switch>
);
return (
<div className="App">
<Layout>
<Suspense fallback={<p>Loading...</p>}>
{routes}
</Suspense>
</Layout>
</div>
);
};
export default App;
我的组件看起来像: - App.js - 布局(不重新渲染)(有3个孩子) - MainPage(无限重新渲染),ServerPing(不重新渲染),NotFoundComponent(不重新渲染)
问题是:为什么MainPage组件无限地重新渲染?我的意思是当套接字数据获取这是奇怪的行为时,MainPage组件及其子组件再次卸载并重新装入。
MainPageComponent:
const MainPage = ({ axiosInstance, ...props }) => {
const isMounted = React.useRef(false);
const [loadingPage, setLoadingPage] = useState(true);
const [usernames, setUsernames] = useState([]);
const [currentDay] = useState(new Date().getDay());
useEffect(() => {
isMounted.current = true;
console.log('[MainPage.js] Mounted!');
getUsers();
return () => {
console.log('[MainPage.js] Unmounted!');
isMounted.current = false;
};
}, []);
const getUsers = async () => {
try {
const res = await axiosInstance.get('/users');
const newData = await res.data;
const newArray = [];
newData.map(user => (
newArray.push({id: user._id, flag: user.flag, text: user.name, value: user.name.toLowerCase()})
));
if (isMounted.current) {
setUsernames(newArray);
setLoadingPage(false);
}
} catch {
if (isMounted.current) {
setLoadingPage(false);
}
}
};
return...
问题是你使用component
prop而不是render
prop到render the MainPage
,如果有一个组件道具的回调,它将重新安装App组件的任何重新渲染组件。
下面的代码应该解决问题
<Route
path={['/', '/users/:id']}
exact
render={(props) => <MainPage {...props} axiosInstance={axiosInstance} />}
/>
根据react-router-dom文档
当您使用组件(而不是渲染或子项,下面)时,路由器使用
React.createElement
从给定组件创建新的React元素。这意味着如果为组件prop提供内联函数,则每次渲染都会创建一个新组件。这导致现有组件卸载和新组件安装,而不是仅更新现有组件。使用内联函数进行内联渲染时,请使用render
或children
prop(下面)。