[英]How to avoid rerender of a component in React?
使用 React 和 Redux 創建一個簡單的應用程序。
關鍵是從服務器獲取照片,顯示它們,如果您單擊帶有更大照片和評論的照片顯示模式窗口。
App組件的代碼
import React, { useEffect } from 'react'
import { useSelector, useDispatch } from 'react-redux'
import './App.scss'
import List from './components/list/List'
import Header from './components/header/Header'
import Footer from './components/footer/Footer'
import ModalContainer from './containers/ModalContainer'
import { getPhotos, openModal } from './redux/actions/actions'
const App = () => {
const { isFetching, error } = useSelector(({ photos }) => photos)
const photos = useSelector(({ photos }) => photos.photos)
const { isOpen } = useSelector(({ modal }) => modal)
const dispatch = useDispatch()
useEffect(() => {
dispatch(getPhotos())
}, [])
const getBigPhoto = (id) => {
dispatch(openModal(id))
}
return (
<div className="container">
<Header>Test App</Header>
<div className="list__content">
{isFetching
? <p>Loading...</p>
: error
? <p>{error}</p>
: photos.map(({ id, url }) => (
<List
key={id}
src={url}
onClick={() => getBigPhoto(id)}
/>
))
}
</div>
<Footer>© 2019-2020</Footer>
{isOpen && <ModalContainer />}
</div>
)
}
export default App
在這一行中,如果我刷新頁面,我只會獲得一次照片以停止重新渲染
useEffect(() => {
dispatch(getPhotos())
}, [])
當我點擊照片時,我的模態打開,我想停止重新渲染所有組件。 例如,對於我的標題,我像這樣使用 React.memo HOC
import React, { memo } from 'react'
import './Header.scss'
import PropTypes from 'prop-types'
const Header = memo(({ children }) => {
return <div className="header">{children}</div>
})
Header.propTypes = {
children: PropTypes.string,
}
Header.defaultProps = {
children: '',
}
export default Header
當我打開和關閉我的模態時,它工作得很好。 頁眉和頁腳不會重新渲染。 但是每次打開和關閉模態窗口時都會重新渲染 List 組件。 發生這種情況是因為 List 組件中的 prop onClick={() => getBigPhoto(id)}
每次單擊時都會創建一個新的匿名函數。 如您所知,如果 props 發生變化,組件會重新渲染。
我的問題是如何避免在我的情況下重新呈現 List 組件?
您可以為 List 創建一個接收 getBigPhoto 和 id 的容器,使用 useCallback 創建 getBigPhoto 以便函數不會改變:
const ListContainer = React.memo(function ListContainer({
id,
src,
getBigPhoto,
}) {
return (
<List
key={id}
src={scr}
onClick={() => getBigPhoto(id)}
/>
);
});
const App = () => {
const { isFetching, error, photos } = useSelector(
({ photos }) => photos
);
const { isOpen } = useSelector(({ modal }) => modal);
const dispatch = useDispatch();
useEffect(() => {
dispatch(getPhotos());
}, []);
//use callback so getBigPhoto doesn't change
const getBigPhoto = React.useCallback((id) => {
dispatch(openModal(id));
}, []);
return (
<div className="container">
<Header>Test App</Header>
<div className="list__content">
{isFetching ? (
<p>Loading...</p>
) : error ? (
<p>{error}</p>
) : (
photos.map(({ id, url }) => (
// render pure component ListContainer
<ListContainer
key={id}
src={url}
id={id}
getBigPhoto={getBigPhoto}
/>
))
)}
</div>
<Footer>© 2019-2020</Footer>
{isOpen && <ModalContainer />}
</div>
);
};
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.