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 to modify data that getting from SWR #402

Closed
keidarcy opened this issue May 18, 2020 · 7 comments
Closed

How to modify data that getting from SWR #402

keidarcy opened this issue May 18, 2020 · 7 comments

Comments

@keidarcy
Copy link

keidarcy commented May 18, 2020

How to migrate this use case to SWR?
Thanks in advance!

const [value, setValue] = useState('')

useEffect(() => {
  const fn = async (() => {
    const {data} = await axios.get(API)
    setValue(data)
    }
  fn()
  }, [value])

return <input value={value} onChange={(e) => setValue(e.currentTarget.value)} />
@huozhi
Copy link
Member

huozhi commented May 18, 2020

you can make the async fn() as fetcher argument for swr, and use value as key. like

const {data} = useSWR(key, async () => { const {data} = await axios.get(API); return data; })

@xyyolab do you mind providing more information about the use case? when user input sth, changes will lead to a new get request and the response data, which will change the value again and it will go into the new cycle?

@keidarcy
Copy link
Author

Thanks for your response!
I'm making a detail page with a form that gets data from API like below.
There is only one submit button with a post request to update(don't need to re-fetch data after load everything).

I figure out this possible way to do my job.

I'm new to SWR which is great! Do you have any advice on this situation?

function productDetail () {

  const [value, setValue] = useState('')
  const [fetched, setFetched] = useState(false)
  const fetcher = (url) => fetch(url).then((r) => r.json())
  const { data } = useSWR(GET_API, fetcher)
  const handleClick = async () => {
     await axios.post(POST_API, {value})
  }

  useEffect(() => {
      if (data) {
        setValue(data.value)
        setFetched(true)
      }
  }, [data])

  if (!fetched) return <div>loading</div>
  return (
    <>
      <input value={value} onChange={(e) => setValue(e.currentTarget.value)} />
      <button onClick={handleClick}>submit</button>
    </>
  )
}

@huozhi
Copy link
Member

huozhi commented May 18, 2020

thanks I think I understand your approach here 😄 looks great. not sure if the fetched could be replaced with isValidating return from useSWR I guess?

const {data, isValidating} = useSWR

if (isValidating) return <div>loading</div>

@sergiodxa
Copy link
Contributor

You need to use the mutate function, either the one returned by useSWR with the key already applied if the one exported by the library without the key already applied.

import { mutate } from “swr”

mutate(key, oldData => newData, false)

Or

const { mutate } = useSWR(key, fetcher)
// ...
mutate(oldData => newData, false)

@keidarcy
Copy link
Author

@sergiodxa
Could you please help me with this full use case?

I think I need to use mutate, but still not sure how to implement it.

function ProductDetail () {

  const [value, setValue] = useState('')
  const [fetched, setFetched] = useState(false)
  const fetcher = (url) => fetch(url).then((r) => r.json())
  const { data } = useSWR(GET_API, fetcher)
  const handleClick = async () => {
     await axios.post(POST_API, {value})
  }

  useEffect(() => {
      if (data) {
        setValue(data.value)
        setFetched(true)
      }
  }, [data])

  if (!fetched) return <div>loading</div>
  return (
    <>
      <input value={value} onChange={(e) => setValue(e.currentTarget.value)} />
      <button onClick={handleClick}>submit</button>
    </>
  )
}

@sergiodxa
Copy link
Contributor

sergiodxa commented May 18, 2020

Something like this should do the work:

const fetcher = (url) => fetch(url).then((r) => r.json());

function ProductDetail() {
  const { data, mutate } = useSWR(GET_API, fetcher, {
    revalidateOnFocus: false, // disable onTabFocus revalidation
  });

  const handleClick = async () => {
    await axios.post(POST_API, { value: data });
    mutate(); // revalidate data
  };

  function handleChange(event) {
    // mutate the data without revalidating it
    mutate(event.currentTarget.value, false);
  }

  if (!data) return <div>loading</div>;

  return (
    <>
      <input value={data} onChange={handleChange} />
      <button onClick={handleClick}>submit</button>
    </>
  );
}

@radomir-mijovic
Copy link

You need to use the mutate function, either the one returned by useSWR with the key already applied if the one exported by the library without the key already applied.

import { mutate } from “swr”

mutate(key, oldData => newData, false)

Or

const { mutate } = useSWR(key, fetcher)
// ...
mutate(oldData => newData, false)

Thanks man, this is what i was looking for

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

5 participants