2

After creating useState Hook For gender, age useState('30'); useState('female'); If you set

http://api.minsu.com/product/${id}?gender=feamle&age=30

I am using react-query(useQuery) for api state management library. It's no different, I'm creating a dynamic page right now and then showing the page based on the id value.

This is an example.

https://api.minsu.com/product/${id}

And on the detailed page, http://api.minsu.com/product/${id}?gender=feamle&age=30 In this way, random data is entered for gender and age, and only specific data of a 30-year-old woman is shown.

select box (option) After choosing female and age as Set the api to https://api.minsu.com/product/${id}?gender=${gender}&age=${age} I want to show the detail page after receiving gender and age through api get according to the selected select by modifying it in this way.

It seems that I am not directly using input and select box, and I do not know how to write query using useState Hook.

But I don't know what to do.

This is my code now.

I thought about it for about an hour. I have created age and gender with setState('').

    const [gender, setGenders] = useState('female');
    const [age, setAges] = useState('30');


   const fetchDetail = async () => {
        const res = await 
        fetch(`https://api.minsu.com/product/${id}?gender=${female}&age=${age}`, {
            headers: {
                Authorization: `Bearer ${token}`,
            },
            withCredentials: true 
        });
        return res.json();
    }

    const { data: ProductDetail, status, error, isFetching } = useQuery('productDetail', fetchDetail, {
        notifyOnChangeProps: ['data'], 
        staleTime: 100000000,
    })
    console.log(ProductDetail);

return (
 

 <input type="number" placeholder={Enter your age} .... />
 <button onClick={onClick} />
 

 <option>Select gender</option>
    <option value="male">Male</option>
    <option value="female">Female</option>
)

That is, to summarize

const [inputs, setInputs] = useState({
        age: '30',
        gender: 'female',
    })
    const {age, gender} = inputs; 

    const onChange = (e) =>{ 
        setInputs({ ...inputs, [e.target.age]:e.target.value }) 
    }

  return (
 <input name="age" onChange={onChange} placeholder = "age"/> 
            <input name="gender" onChange={onChange} placeholder = "gender"/>

)

I want to change the query by executing onChange after creating the input, but the rendering is not working.

ssksksks
  • 209
  • 1
  • 8
  • Is the issue that the URL that gets fetched doesn't update when you update the form? – Henry Woody Nov 04 '21 at 05:34
  • @HenryWoody Yes, that's right. How to update the query after receiving age and gender as input(age), gender(selectbox) – ssksksks Nov 04 '21 at 05:35
  • Is this the same issue as https://stackoverflow.com/questions/69834291/react-enter-as-api-optional-state-gender-gender? In either case it's still unclear what the issue is. If I had to take a guess after looking at the useQuery docs, you need to update the `queryKey` argument to trigger the hook. – Drew Reese Nov 04 '21 at 05:35
  • @DrewReese I don't know if I need to change the query to setState with age and gender. – ssksksks Nov 04 '21 at 05:36
  • Does this answer your question? [Get form data in ReactJS](https://stackoverflow.com/questions/23427384/get-form-data-in-reactjs) – Henry Woody Nov 04 '21 at 05:37
  • @HenryWoody How do I change the query value when onSubmit of form age and gender? – ssksksks Nov 04 '21 at 05:39
  • The link I provided above should answer your question, basically you need to connect your form and your state. I'd go with the accepted answer (not the highest voted) because it's the most straightforward and works best for this usecase (albeit using class components). See also [React Forms](https://reactjs.org/docs/forms.html). If your state variables update according to the form, the URL will update automatically as well. Also you have a typo, you need to swap `gender=${female}` with `gender=${gender}`. – Henry Woody Nov 04 '21 at 05:41
  • What part are you stuck on? You still haven't clarified what the issue is. – Drew Reese Nov 04 '21 at 05:50
  • I don't know if I need to change the query to setState with age and gender. ```code const [inputs, setInputs] = useState({ age: '30', gender: 'female', }) const {age, gender} = inputs; const onChange = (e) =>{ setInputs({ ...inputs, [e.target.age]:e.target.value }) } ``` I wrote it like this, but rendering is not working. Is the value not initialized even after rendering? – ssksksks Nov 04 '21 at 05:56
  • @ssksksks That looks pretty close, only issue is that you're using `e.target.age` as a key, what you want is to use the `name` of the input, like this: `setInputs({...inputs, [e.target.name]: e.target.value })` – Henry Woody Nov 04 '21 at 06:03
  • I don't know what you mean by "change the query to setState with age and gender" but as far as the inputs and updating the `age` and `gender` state that looks close to correct, though you should use the event target's `name` property. From here I think you need to use these values as a computed query key for the `useQuery` hook. – Drew Reese Nov 04 '21 at 06:03
  • @HenryWoody So how should I fix it?? – ssksksks Nov 04 '21 at 06:09

2 Answers2

0

Assuming you're updating the local state (age and gender) correctly and just need to trigger the query again.

Query Basics

To subscribe to a query in your components or custom hooks, call the useQuery hook with at least:

  • A unique key for the query
  • A function that returns a promise that:
    • Resolves the data, or
    • Throws an error

The unique key you provide is used internally for refetching, caching, and sharing your queries throughout your application.

If your query function depends on a variable, include it in the query key.

Given the request URL:

`https://api.minsu.com/product/${id}?gender=${gender}&age=${age}`

Then id, age, and gender should all probably be included as part of the query key.

const {
  data: ProductDetail,
  status,
  error,
  isFetching,
} = useQuery(
  ['productDetail', id, age, gender],
  fetchDetail,
  {
    notifyOnChangeProps: ['data'], 
    staleTime: 100000000,
  },
);
Drew Reese
  • 165,259
  • 14
  • 153
  • 181
  • applied. But I looked up the query key , but I don't know how to change the value of ${age} ${gender} . – ssksksks Nov 04 '21 at 06:15
  • @ssksksks That is what the state updates do. Can you just provide your complete code so we can see what it is you are trying to do instead of this back and forth between "Do you need help updating state?" and "Do you need help updating the query?" – Drew Reese Nov 04 '21 at 06:17
  • I need to change the query. But isn't it possible to change the query by changing the state? – ssksksks Nov 04 '21 at 06:20
  • @ssksksks On state change alone, no. You need to update the state to trigger a rerender, the updated state is essentially a dependency for the `useQuery` React hook. It hashes this "dependency" into a key so if you make the same request again and haven't invalidated the response then the request isn't made to the network, otherwise a new network request is made. – Drew Reese Nov 04 '21 at 06:23
  • useQuery supports it! So what should I do now? – ssksksks Nov 04 '21 at 06:26
0

you can use this (check my comments inside snippet):

import { useQueryClient } from "@tanstack/react-query";

const [id, setId] = useState("someId") // you don't say what should we do with id?!
const [age, setAge] = useState("30")
const [gender, setGender] = useState("female")

const onAgeChange = (e) => {
  setAge(e.target.value) // you used: e.target."""age"""!
}
const onGenderChange = (e) => {
  setGender(e.target.value) // you used: e.target."""age"""!
}

const {
  data: ProductDetail,
  status,
  error,
  isFetching,
} = useQuery(
  ['productDetail', id, age, gender],
  fetchDetail,
  {
    notifyOnChangeProps: ['data'],
    staleTime: 100000000,
  },
);

const queryClient = useQueryClient();
useEffect(() => {
  queryClient.invalidateQueries(['productDetail', id, age, gender]); // this will update your data automatically if id, age and/or gender change
}, [id, age, gender])

return (
  <>
    <input name="age" onChange={onAgeChange} value={inputs.age} placeholder="age" /> {/*  you missed the """value={}""" */}
    <input name="gender" onChange={onGenderChange} value={inputs.gender} placeholder="gender" /> {/*  you missed the """value={}""" */}
  </>
)