reactjs - Dekonstruera state i useState i React och TypeScript


Finns det ett sätt att destrukturera ett nuvarande tillstånd som har en specificerad form? Jag har ett nuvarande tillstånd i personJob men jag vill kunna specificera vilken objekt jag ska titta på (när jag klickar på en knapp som kommer att skära ut det specifika objektet och rendera endast de uppgifterna).

Jag får ett fel i TypeScript const {company, dates, duties, title}=personJob[value]; när jag försöker skiva vid det indexet

Felet är:

Cannot destructure property 'company' of 'personJob[value]' as it is undefined.

Komponent :

import React, { useState, useEffect } from 'react';
import axios from 'axios';

const url = 'https://course-api.com/react-tabs-project';

interface IPerson {
    id: string;
    company: string;
    dates: string;
    duties: string[];
    title: string;
}

function App() {
    const [personJob, setPersonJob] = useState<IPerson[]>([]);
    const [value, setValue] = useState<number>(0);

    const fetchData = async () => {
        const response = await axios(url);
        setPersonJob(response.data);
    };

    useEffect(() => {
        fetchData();
    }, []);

    const { company, dates, duties, title, id } = personJob[value];

    return (
        <main>
            <h1>Jobs</h1>
            {personJob.map((job, index) => {
                return (
                    <button key={job.id} onClick={() => setValue(index)}>
                        {job.company}
                    </button>
                );
            })}
            <section>
                <article className="border-2 px-5 py-5">
                    <div key={id}>
                        <h2>{title}</h2>
                        <h3>{company}</h3>
                        <p>{dates}</p>
                        {duties.map((duty) => {
                            return <div>*** {duty}</div>;
                        })}
                        <button type="button">More Info</button>
                    </div>
                </article>
            </section>
        </main>
    );
}

export default App;

Svar #1

Problem

Vid den första renderingen är personJob fortfarande en tom array och personJob[0] är undefined, så värden kan inte destruktureras från den.

Lösning

  1. Ange ett reservobjekt att destrukturera från, personJob[value] || {}.
  2. Villkorligt rendera section om personJob[value] är sanningsenlig och existerar.

Kod :

function App() {
  const [personJob, setPersonJob] = useState<IPerson[]>([]);
  const [value, setValue] = useState<number>(0);

  const fetchData = async () => {
    const response = await axios(url);
    setPersonJob(response.data);
  };

  useEffect(() => {
    fetchData();
  }, []);

  const { company, dates, duties, title, id } = personJob[value] || {}; // <-- fallback for destructuring

  return (
    <main>
      <h1>Jobs</h1>
      {personJob.map((job, index) => {
        return (
          <button key={job.id} onClick={() => setValue(index)}>
            {job.company}
          </button>
        );
      })}
      {personJob[value] && <section> // <-- conditionally render section if data available
        <article className="border-2 px-5 py-5">
          <div key={id}>
            <h2>{title}</h2>
            <h3>{company}</h3>
            <p>{dates}</p>
            {duties.map((duty) => {
              return <div>*** {duty}</div>;
            })}
            <button type="button">More Info</button>
          </div>
        </article>
      </section>}
    </main>
  );
}

Demo