Была такая же проблема. Я не знаю, почему они не упоминают об этом в документах. Просто хочу немного добавить к ответу Тобиаса Хаугена.
Для запуска каждого компонента / родительского перерисовки вам необходимо использовать:
useEffect(() => {
// don't know where it can be used :/
})
Чтобы выполнить что-либо только один раз после монтирования компонента (будет обработано один раз), вам нужно использовать:
useEffect(() => {
// do anything only one time if you pass empty array []
// keep in mind, that component will be rendered one time (with default values) before we get here
}, [] )
Для запуска чего-либо один раз при монтировании компонента и в данных / данных2 изменить:
const [data, setData] = useState(false)
const [data2, setData2] = useState('default value for first render')
useEffect(() => {
// if you pass some variable, than component will rerender after component mount one time and second time if this(in my case data or data2) is changed
// if your data is object and you want to trigger this when property of object changed, clone object like this let clone = JSON.parse(JSON.stringify(data)), change it clone.prop = 2 and setData(clone).
// if you do like this 'data.prop=2' without cloning useEffect will not be triggered, because link to data object in momory doesn't changed, even if object changed (as i understand this)
}, [data, data2] )
Как я использую его большую часть времени:
export default function Book({id}) {
const [book, bookSet] = useState(false)
useEffect(() => {
loadBookFromServer()
}, [id]) // every time id changed, new book will be loaded
async function loadBookFromServer() {
let response = await fetch('api/book/' + id)
response = await response.json()
bookSet(response)
}
if (!book) return false //first render, when useEffect did't triggered yet we will return false
return <div>{JSON.stringify(book)}</div>
}