Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

how does swr work with useEffect??request many times when props change. #77

Closed
nai6514531 opened this issue Nov 5, 2019 · 8 comments
Closed

Comments

@nai6514531
Copy link

nai6514531 commented Nov 5, 2019

it‘s my first time to use this library. useSWR('/api/data', fetchData) will excute when App props changes. how can i use useEffect let it only work in componentDidMount..it seems not work in useEffect.

import useSWR from 'swr'
import fetchData from './fetch-data'

function App () {
  const { data } = useSWR('/api/data', fetchData)
  // ...
}`
expect
`import useSWR from 'swr'
import fetchData from './fetch-data'

function App () {
useEffect(() => {
 const { data } = useSWR('/api/data', fetchData)
  // ...
}, [])
}
@nai6514531 nai6514531 changed the title request many times when props change how swr work with useEffect??request many times when props change. Nov 5, 2019
@nai6514531 nai6514531 changed the title how swr work with useEffect??request many times when props change. how does swr work with useEffect??request many times when props change. Nov 5, 2019
@shuding
Copy link
Member

shuding commented Nov 5, 2019

You can't call hooks inside useEffect: https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level

Instead you can do this:

function App () {
  const [mounted, setMounted] = useState(false)
  const { data } = useSWR(mounted ? '/api/data' : null, fetchData)

  useEffect(() => {
    setMounted(true)
  }, [])
}

When key is null, SWR will pause itself. It's also explained here https://github.com/zeit/swr#key-as-a-function.

@shuding shuding closed this as completed Nov 5, 2019
@moroshko
Copy link

@quietshu Maybe I'm missing the intent here, but wouldn't fetch happen on every rerender this way? (since mounted is going to be always true)

@shuding
Copy link
Member

shuding commented Nov 25, 2019

@moroshko nope, SWR isn't like the normal fetch call. It will reuse the result, and only fetch again in certain cases by default (for example if you refocus on the window).

@corysimmons
Copy link

@shuding My fetched URL changes depending on some <select>. How does SWR handle that without useEffect?

That is... how can I accomplish something like below if I can't nest useSWR?

const [selectOption, setSelectOption] = useState()

useEffect(() => {
  useSWR(`https://api.example.com/${selectOption}`) // 🚨 can't nest hooks
}, [selectOption])

return (
  <select>...</select>
)

@shuding
Copy link
Member

shuding commented Jun 22, 2020

@corysimmons you can just remove that useEffect:

const [selectOption, setSelectOption] = useState()
useSWR(`https://api.example.com/${selectOption}`)

return (
  <select>...</select>
)

@corysimmons
Copy link

@shuding Awesome. btw I like your Github quote and domain name. Thanks for the nice library!

@daviesdoclc
Copy link

daviesdoclc commented Jul 13, 2020

I'm having this same issue. I'm using the setMounted technique shown above. However, I still see network requests to my SWR endpoint when I change another property on the component and render gets called. Maybe SWR always makes the call in DEV mode?

If I add revalidateOnFocus: false to the SWR request then it seems to work. I'm testing this in Chrome developer tools. I wonder if it's doing something funky.

@sergiodxa
Copy link
Contributor

RevalidateOnFocus make SWR run a new fetch every time the tab recover focus, when you focus on the browser DevTools the tab lose focus, when you click again in the page it will recover the focus and revalidate the data triggering a new request.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants