Home > Net >  React Query only display on tab refresh
React Query only display on tab refresh

Time:11-16

I find myself in a bit of a pickle and can't seem to find an answer on Google.

I'm trying to use the React query library with TSX and display the returning data in a simple list. However it seems that the fetchng and displaying is done only by leaving the tab and coming back to it.

Here's the component

import React, { ChangeEvent, useState, ReactElement } from "react";
import { useQuery, UseQueryResult } from "react-query";
import axios from "axios";

import { API_URL } from "../../settings";

import SearchBar from "../../components/search-bar";

const Employees = (): ReactElement => {
  type Employee = Record<string, any>;

  const [name, setName] = useState("");

  function getValue(eventData: ChangeEvent<HTMLInputElement>) {
    console.log(name, "I'm the direct input");
    const e = eventData.target.value;
    setName(e);
    getEmployeesList(name);
  }

  async function getEmployeesList(name: string) {
    const { data } = await axios.get(
      API_URL   "employees?q[firstname_or_lastname_cont]="   name
    );
    console.log(data);
    return data;
  }

  const {
    data,
    error,
    isError,
    isLoading,
  }: UseQueryResult<Employee[], Error> = useQuery("employees", () =>
    getEmployeesList(name)
  );
  if (isLoading) {
    return <div>Loading...</div>;
  }
  if (isError) {
    return (
      <div>
        `Error!
        {error?.message}`
      </div>
    );
  }
  if (data) {
    console.log(data, "I'm the query data");
  }

  return (
    <div className="findEmployees">
      <SearchBar
        placeholder=""
        value={name}
        onValueChange={(event: ChangeEvent<HTMLInputElement>) =>
          getValue(event)
        }
      />
      <div className="listContainer">
        <h1>Employees</h1>
        {data?.map((employee, index: number) => (
          <li key={employee.id}>
            {employee.firstname} {employee.lastname}
            <p>{employee.role}</p>
          </li>
        ))}
      </div>
    </div>
  );
};

export default Employees;
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

Here's the child component

import React, {
  ChangeEventHandler,
  MouseEvent,
  ReactElement,
  ReactEventHandler,
} from "react";
import { SearchBarContainer, SearchBarInput } from "./styled-components";
import Icon from "../icon";

interface Props {
  placeholder: string;
  value: string;
  onValueChange: ChangeEventHandler<HTMLInputElement>;
}

const SearchBar = ({
  onValueChange,

  placeholder,
  value,
}: Props): ReactElement => (
  <SearchBarContainer>
    <SearchBarInput
      onChange={onValueChange}
      placeholder={placeholder}
      value={value}
    />

    <Icon color="grey700" name="search" />
  </SearchBarContainer>
);

export default SearchBar;
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

So far I haven't found the problem. I tried a custom hook to get and set the data but that obviously didn't change the problem. If anyone has an idea I'll be thankful.

Have a great day

CodePudding user response:

function getValue(eventData: ChangeEvent<HTMLInputElement>) {
    const e = eventData.target.value;
    setName(e);
    console.log(name); // still you should receive previous value
    getEmployeesList(e);
  }

setState isn't synchronous. It only updates the state value at end of the function call.

CodePudding user response:

thanks for your inputs. I actually solved the problem with a custom hooks

import React, { ChangeEvent, useState, ReactElement } from "react";
import { useQuery, UseQueryResult } from "react-query";
import axios from "axios";

import { API_URL } from "../../settings";

import SearchBar from "../../components/search-bar";

const Employees = (): ReactElement => {
  type Employee = Record<string, any>;

  const [name, setName] = useState<string>("");
  const [eData, setEData] = useState<Employee[]>([]);

  function getValue(eventData: ChangeEvent<HTMLInputElement>) {
    setName(eventData.target.value);
    getEmployeesList(eventData.target.value);
  }

  async function getEmployeesList(name: string) {
    const { data } = await axios.get(
      API_URL   "employees?q[firstname_or_lastname_cont]="   name
    );
    setEData(data);
    return data;
  }

  const {
    data,
    error,
    isError,
    isLoading,
  }: UseQueryResult<Employee[], Error> = useQuery("employees", () =>
    getEmployeesList(name)
  );
  if (isLoading) {
    return <div>Loading...</div>;
  }
  if (isError) {
    return (
      <div>
        `Error!
        {error?.message}`
      </div>
    );
  }

  return (
    <div className="findEmployees">
      <SearchBar
        placeholder=""
        value={name}
        onValueChange={(event: ChangeEvent<HTMLInputElement>) =>
          getValue(event)
        }
      />
      <div className="listContainer">
        <h1>Employees</h1>
        {eData?.map((employee, index: number) => (
          <li key={employee.id}>
            {employee.firstname} {employee.lastname}
            <p>{employee.role}</p>
          </li>
        ))}
      </div>
    </div>
  );
};

export default Employees;
<iframe name="sif3" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

As you can see I changed "data" by the hook value "eData". I noticed that my axios query was updated in real time so I took this entry and stocked it in a custom hook which I then mapped on my JSX. Got a real time fetch that way. Furthermore I updated the

function getValue(eventData: ChangeEvent<HTMLInputElement>) {
setName(eventData.target.value);
getEmployeesList(eventData.target.value);

}

part which was requesting with one letter fewer in the first version.

  • Related