Search code examples
reactjsreact-routersetstateuse-state

Dynamic routing getting undefined


The API I'm using receives a phone number as a parameter to return data from a user. So in the UI, I receive this number and through console.log I can see the data. But I also want, when clicking the button the user is taken to a link containing only data related to them and to do that I believe that I have to redirect the user to a dynamic link eg: '/user/john'. I'm always getting undefined in the link and I have no idea why. It feels like the state itself is not storing the API data

const Login =()=> {
  const history = useHistory()
  const location = useLocation()
  const [state, setState] = useState('')
  const [data, setData] = useState({});
  const phone = state
...
  let headers = new Headers();
  headers.set("Authorization", "Basic " + btoa(username + ":" + password));

    const handleClick=() => {
    getData();
  };    
  
  const getData = async () => {
    const a = await fetch(url, { method: "GET", headers: headers });
    const response = await a.json();
    setData(response.user[0].attributes[0]);
    history.push(`/user/${data.name}`)
  };
  
   const onTextChange = event => {
        setState(event.target.value);
      }
<input onChange={onTextChange}>
 <Button  onClick={handleClick} >
    login
 </Button> 

Solution

  • State always sets asynchronously (more details). setData(response.user[0].attributes[0]) will take some and since js is asynchronous next line will be executed i.e history.push('/user/${data.name}'). Since there is no data yet so data.name will be undefined.

    Instead you must directly use history.push(/user/${(response.user[0].attributes[0]).name})

    Here is the updated code:

        const Login = () => {
        const history = useHistory()
        const location = useLocation()
        const [state, setState] = useState('')
        const [data, setData] = useState({});
        const phone = state
        ...
        let headers = new Headers();
        headers.set("Authorization", "Basic " + btoa(username + ":" + password));
    
        const handleClick = () => {
        getData();
        };
    
        const getData = async () => {
        const a = await fetch(url, { method: "GET", headers: headers });
        const response = await a.json();
        const respData = response.user[0].attributes[0]
        setData(respData);
        history.push(`/user/${respData.name}`)
        };
    
        const onTextChange = event => {
        setState(event.target.value);
        }
        <input onChange={onTextChange}>
        <Button onClick={handleClick} >
          login
        </Button>