skip to Main Content

I have a page with two components: table and header.

Page:

import Header from '@/components/header/header.js';
import Table from '@/components/table/table.js';

export default function TablePage() {

  return (
    <div>

      <Header />
      <main>
        <Table></Table>
      </main>
    </div>
  )
}

Header Component:

import { useRouter } from 'next/router'
import styles from './header.module.css';

function search(e, router) {
  e.preventDefault();
  const string = e.target.querySelector('input').value;
  router.push('/table_page');
}

export default function Header () {
  const router = useRouter()

  return (
    <header className={styles.header}>
      <div className={styles.search}>
        <form onSubmit={(e) => {search(e, router)}}>
          <button type='submit'></button>
          <input type='search' placeholder='Type song or artist name'/>
        </form>
      </div>
    </header>
  )
}

Table Component:

import styles from './table.module.css';
import { useState, useEffect } from 'react';
import data from '@/youtube_data.json';

export default function Table() {

  let [myArray, updateMyArray] = useState([]);

  function handleSearchQuery(string) {
    updateMyArray(() => {
      const result = data.filter(item => item.title.match(string));
      return result;
    });
  }
  
  useEffect(() => {
    updateMyArray( () => {
      return data;
    });
  });

  return (
    <div className={styles.table}>
      <table>
        <thead>
          <tr>
            <th>
              Title
            </th>         
          </tr>
        </thead>
        <tbody>
            {myArray.map(item =>
              <tr key={item.id}>
                <td>
                   {item.title}              
                </td>
              </tr>
            )}
        </tbody>
      </table>
    </div>
  );
}

I need to somehow call the handleSearchQuery function by entering a query into input of the header component and upate the table component based on a string from the input search (it is a filter for searching through an array of data). How to do it?
I’m sure it’s simple enough, but I’m stuck on it.

2

Answers


  1. One way is in header component you set the query parameter when user searches. Since every page renders the Header in the table page you have Header and table. In the Header

    export default function Header () {
      const router = useRouter()
      const [searchKey,setSearchKey=useState("")
    
      return (
        <header className={styles.header}>
          <div className={styles.search}>
            // when user submits the input set the query param
            <form onSubmit={() => {
              if (searchKey === "") return;
              // this will add query param
              router.push(`/?key=${searchKey}`);
              setLocation("");
            }}>
              <button type='submit'></button>
              // when user enters value, set the state value
              <input type='search' placeholder='Type song or artist name'
                     onChange={(e) => setSearchKey(e.target.value)}
              />
            </form>
          </div>
        </header>
      )
    }
      
    

    then you read the query param

    // we named it key above
    const { key } = router.query;
    

    based on this value you update the myArray state value in useEffect

    useEffect(()=>{
       updateMyArray(myArray.filter(item => item.title.match(key)))
       // [key] is dependency array
       // when "key" changes, your component will be updated and you will have filtered state value
    },[key])
    
    Login or Signup to reply.
  2. There’s no need for a function at all.

    Update the query param whenever the user types, in Header.
    Read the query param using the hook, in the Table.

    Flow:

    1. User -> edits input in Header -> query param is updated.
    2. Table re-renders, since it’s using the useRouter hook.

    That’s it

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search