1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ReactHookFormでクエリパラメータを更新し、API通信する。

Last updated at Posted at 2024-06-18

はじめに

表題通り、ReactHookFormでクエリパラメータを更新し、クエリパラメータの変更を検知する事でAPI通信する仕組みを作ります。やりたい事は下記の図の通りです。

スクリーンショット 2024-06-18 21.46.12.png

成果物

jsonplaceholder.gif

ソースコード

src/App.tsx
import React from 'react';
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
import { Container, Typography } from '@mui/material';
import { JsonPlaceHolder } from './components'

const App: React.FC = () => {
  return (
    <Router>
      <Container>
        <Typography variant="h4" component="h1" gutterBottom>
          Search Example with React Hook Form
        </Typography>
        <Routes>
          <Route path="/" element={<JsonPlaceHolder />} />
        </Routes>
      </Container>
    </Router>
  );
};

export default App;

src/components/index.tsx
import { useQueryParams, useFetchData } from "./hooks"
import SearchForm from "./SearchForm"
import { SearchResult } from "./SearchResult"


export const JsonPlaceHolder = () => {
  const query = useQueryParams();
  const { results, loading } = useFetchData(query);

  return (
    <div>
      <h1>JsonPlaceHolder</h1>
      <SearchForm />
      <SearchResult results={results} loading={loading} />
    </div>
  );
};
src/components/SearchForm.tsx
import { useForm } from 'react-hook-form';
import { TextField, Button, Box } from '@mui/material';
import { useLocation, useNavigate } from 'react-router-dom';
import queryString from 'query-string';

type SearchFormData = {
  query: string;
};

const SearchForm = () => {
  const location = useLocation();
  const navigate = useNavigate();
  const params = queryString.parse(location.search);
  const defaultQuery = params.query as string || '';

  const { register, handleSubmit } = useForm<SearchFormData>({
    defaultValues: { query: defaultQuery }
  });


  const onSubmit = (data: SearchFormData) => {
    const newQuery = queryString.stringify({ query: data.query });
    navigate(`?${newQuery}`);
  };
  return (
    <Box>
      <form onSubmit={handleSubmit(onSubmit)}>
        <TextField
          label="Search"
          {...register('query')}
          variant="outlined"
          fullWidth
          margin="normal"
        />
        <Button type="submit" variant="contained" color="primary">
          Search
        </Button>
      </form>
    </Box>
  );
};

export default SearchForm;
src/components/SearchResult.tsx
import { Box, CircularProgress, List, ListItem, ListItemText } from '@mui/material';

type SearchResultProps = {
    results: any[];
    loading: boolean;
};

export const SearchResult = ({ results,loading}:SearchResultProps) => {
  return (
    <Box mt={4}>
      {loading ? (
        <Box display="flex" justifyContent="center">
          <CircularProgress />
        </Box>
      ) : (
        <List>
          {results.map((result) => (
            <ListItem key={result.id}>
              <ListItemText primary={result.title} />
            </ListItem>
          ))}
        </List>
      )}
    </Box>
  );
};

hooks.tsx
import { useLocation } from "react-router-dom";
import { useState, useEffect } from "react";
import queryString from "query-string";
import axios from "axios";

export const useQueryParams = () => {
    const location = useLocation();
    const params = queryString.parse(location.search);
    const queryParam = params.query as string || '';
  
    return queryParam;
  };
  
 export const useFetchData = (query: string) => {
    const [results, setResults] = useState<any[]>([]);
    const [loading, setLoading] = useState<boolean>(false);
  
    useEffect(() => {
      const fetchData = async () => {
        setLoading(true);
        try {
          const response = await axios.get('https://jsonplaceholder.typicode.com/posts', {
            params: { q: query }
          });
          setResults(response.data);
        } catch (error) {
          console.error('Error fetching data:', error);
          setResults([]);
        } finally {
          setLoading(false);
        }
      };
  
      if (query) {
        fetchData();
      } else {
        setResults([]);
      }
    }, [query]);
  
    return { results, loading };
  };
  
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?