Преобразование компонента класса в функциональный с интерфейсом typescript

#javascript #reactjs #typescript

#javascript #reactjs #typescript

Вопрос:

У меня есть следующий компонент на основе классов. И мне пришлось преобразовать его в функциональный компонент

 import React from 'react'

import { API } from '../../api'
import { JobPosting } from '../../types'
import { JobPostings } from './JobPostings'

interface State {
  jobPostings: JobPosting[]
  loading: boolean
}

export class JobPostingsPage extends React.Component<{}, State> {
  state = {
    jobPostings: [],
    loading: true,
  }

  componentDidMount() {
    API.jobPostings.loadAll().then(({ data }) => {
      this.setState({
        jobPostings: data,
        loading: false,
      })
    })
  }

  render() {
    if (this.state.loading) {
      return null
    }

    return (
      <div>
        <h1>Job Postings</h1>

        <JobPostings jobPostings={this.state.jobPostings} />
      </div>
    )
  }
}
 

Теперь я хочу преобразовать вышеуказанный класс на основе функционального компонента. Итак, я использовал useState и useEffect и преобразовал его в функциональный, как показано ниже

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

import { API } from '../../api'
import { jobPostings } from '../../api/jobPostings'
import { JobPosting } from '../../types'
import { JobPostings } from './JobPostings'

interface State {
  jobPostings: JobPosting[]
  loading: boolean
}

export const JobPostingsPage: React.FC<State> = ({} ) => {
  const [jobPostings, setJobPostings] = useState<JobPosting[]>([]);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    API.jobPostings.loadAll().then(({ data }) => {
      setJobPostings(data);
      setLoading(false)
    })
  })

  return(
    loading ? null: (
      <div>
        <h1>Job Postings</h1>

        <JobPostings jobPostings={jobPostings} />
      </div>
    )
  )}
 

Проблема, с которой я сталкиваюсь, заключается в том, что он выдает ошибку при запуске npm. В нем говорится
Type '{}' is missing the following properties from type 'State': jobPostings, loading TS2739

Это указывает на приведенный ниже код в файле маршрутизатора

 
const routes = {
  home: '/',
}

export const Router: React.FC = () => (
  <BrowserRouter>
    <Switch>
      <Route exact path={routes.home}>
        <JobPostingsPage /> -------------------> ERROR ON THIS LINE <------------
      </Route>
    </Switch>
  </BrowserRouter>
)
 

Любая идея, где я ошибаюсь с преобразованием. Пожалуйста, любой ввод приветствуется.

Ответ №1:

Проблема в этой строке:

 export const JobPostingsPage: React.FC<State> = ({} ) => {
 

Здесь должно быть props определено вместо состояния. Из компонента класса я понимаю, что реквизиты пусты, поэтому вы должны обменять его на это и все будет в порядке:

 export const JobPostingsPage: React.FC<{}> = ({} ) => {
 

Ответ №2:

 import React from "react";
import BootstrapTable from "react-bootstrap-table-next";
import filterFactory, {
  textFilter,
  customFilter
} from "react-bootstrap-table2-filter";

class PriceFilter extends React.Component {
  constructor(props) {
    super(props);
    this.filter = this.filter.bind(this);
    this.getValue = this.getValue.bind(this);
  }
  getValue() {
    return {
      min: this.min.value,
      max: this.max.value
    };
  }
  filter() {
    this.props.onFilter(this.getValue());
  }
  render() {
    return [
      <input
        key="min"
        ref={(node) => (this.min = node)}
        type="date"
        placeholder="Min price"
      />,
      <input
        key="max"
        ref={(node) => (this.max = node)}
        type="date"
        placeholder="max price"
      />,
      <button key="submit" className="btn btn-warning" onClick={this.filter}>
        {`Filter ${this.props.column.text}`}
      </button>
    ];
  }
}

const filterDate = (filterVals, data) => {
  console.log(filterVals);
  console.log(data);
  let min = new Date(
    parseInt(filterVals.min.substring(0, 4), 10),
    parseInt(filterVals.min.substring(5, 7), 10) - 1,
    parseInt(filterVals.min.substring(8, 10), 10)
  );
  let max = new Date(
    parseInt(filterVals.max.substring(0, 4), 10),
    parseInt(filterVals.max.substring(5, 7), 10) - 1,
    parseInt(filterVals.max.substring(8, 10), 10)
  );

  const filteredData = data.filter(
    // here this is not books but this is undefined here
    (row) => {
      let datejs = new Date(
        parseInt(row.date.substring(0, 4), 10),
        parseInt(row.date.substring(5, 7), 10) - 1,
        parseInt(row.date.substring(8, 10), 10)
      );
      console.log(datejs);
      console.log(min);
      console.log(
        ((min amp;amp; datejs >= min) || !filterVals.min) amp;amp;
          ((max amp;amp; datejs <= max) || !filterVals.max)
      );

      return (
        ((min amp;amp; datejs >= min) || !filterVals.min) amp;amp;
        ((max amp;amp; datejs <= max) || !filterVals.max)
      );
    }
  );
  console.log(filteredData);
  return filteredData;
};

const columns = [
  {
    dataField: "id",
    text: "Product ID"
  },
  {
    dataField: "name",
    text: "Product Name",
    filter: textFilter()
  },
  {
    dataField: "date",
    text: "Date",
    filter: customFilter({
      onFilter: filterDate
    }),
    filterRenderer: (onFilter, column) => (
      <PriceFilter onFilter={onFilter} column={column} />
    )
  }
];

const products = [
  {
    id: 0,
    name: "Product 1",
    date: "2021-12-24"
  },
  {
    id: 1,
    name: "Product 2",
    date: "2022-01-02"
  },
  {
    id: 2,
    name: "Product 3",
    date: "2022-01-05"
  },
  {
    id: 3,
    name: "Product 4",
    date: "2022-01-07"
  }
];

const Table = () => {
  return (
    <BootstrapTable
      keyField="id"
      data={products}
      columns={columns}
      filter={filterFactory()}
    />
  );
};

export default Table;
I need to help convert to function componant