Реагируйте с Typescript: несоответствие типов - PullRequest
0 голосов
/ 12 апреля 2019

некоторое время назад начал использовать React с машинописью, но всегда путался с типами и ожидаемым элементом React.

как в этом сценарии (Также песочница здесь ) Я получаю следующую ошибку дляТодос Компонент

в VSCODE с более симпатичной настройкой TSLint: Тип '(props: PropsWithChildren) => Элемент []' нельзя назначить типу 'FunctionComponent'.

в Snadbox: Тип '(props: IProps) => void []' нельзя назначить типу 'FunctionComponent'.


    import { TodoStore } from "./stores/TodoStore";
    import { observable } from "mobx";
    interface IProps {
      todoStore: TodoStore;
    }
   // red underline at `TodoComp` with mentioned error message
    const TodosComp: React.FC<IProps> = props => {
      const { todos } = props.todoStore;
      return todos.map(todo => {
        <div key={todo.id}>
          <p>{todo.title}</p>
          <select />
        </div>;
      });
    };
    export default inject("todoStore")(observer(TodosComp));

Хранилище Mobx для задач похоже на

import { decorate, observable, runInAction, action } from 'mobx';
export interface ITodo {userId: number; id: number; title: string; completed: boolean;
}
export class TodoStore {
  public todos: ITodo[];
  constructor() {
    this.todos = [];
    this.fetchTodos();
  }

  public async fetchTodos() {
    const response = await fetch('http://jsonplaceholder.typicode.com/todos');
    const todos: ITodo[] = await response.json();
    runInAction(() => {
      this.todos = todos;
    });
 }}
decorate<TodoStore>(TodoStore, { todos: observable, fetchTodos: action });

Проблема в Mobx и если сам класс используется в качестве типа в компоненте?классам mobx нужен отдельный интерфейс?

Кроме того, как специфический вопрос для Mobx, является ли правильный путь в песочнице для создания экземпляра класса хранилища у провайдера?

в общем, если кто-то знает хорошую статью о React с машинописным текстом, как оценивать реквизиты и типы JSX, был бы признателен.

Ответы [ 2 ]

2 голосов
/ 12 апреля 2019

Функция должна возвращать JSX.Element, и вам нужно передать div или Fragment, это должно работать.

const Todos: React.FC<IProps> = (props: IProps): JSX.Element => {
  const { todos } = props.todoStore;
  return (<React.Fragment>
    {todos.map(todo => {
      <div key={todo.id}>
        <p>{todo.title}</p>
        <select />
      </div>;
    })}
  </React.Fragment>);
};
1 голос
/ 12 апреля 2019

FunctionComponent определяется как

interface FunctionComponent<P = {}> {
  (props: PropsWithChildren<P>, context?: any): ReactElement | null;
  ...

, где ReactElement равно

interface ReactElement<P = any, T extends string | JSXElementConstructor<any> = string | JSXElementConstructor<any>> {
  type: T;
  props: P;
  key: Key | null;
}

Из этих определений вы можете сказать, что вы не можете вернуть массив из React.FC.Решение состоит в том, чтобы обернуть ваше возвращаемое значение в реагирующий фрагмент как

return (
  <>
    {todos.map(todo => {
      <div key={todo.id}>
        <p>{todo.title}</p>
        <select />
      </div>;
    })}
  </>
);
...