@dualdeazz

Почему стек вызовов переполнен?

Почему-то выдает ошибку о переполненном стеке вызовов, как исправить?
Рекурсивный компонент
import React, {FC, ReactNode} from 'react';
import { observer } from 'mobx-react-lite';
import { Comment } from './Comment';

interface IRecursiveProps {
    data: any,
    getChildren: Function,
}

const RecursiveComponent:FC<IRecursiveProps> = observer(({data,getChildren}) => {
    return (
        <div>
            {data.map((parent:any) => {
                return (
                    <Comment parent={parent} getChildren={getChildren} data={data}/>
                );
            })}
        </div>
    );
});

export default RecursiveComponent;

Компонент коммента
import React,{FC} from 'react';
import { IComment } from '../store/Comments';
import RecursiveComponent from  "./RecrusiveComponents"
import { dateParser } from '../utils/dateParser';
import { observer } from 'mobx-react-lite';

interface ICommentProps {
    data: IComment[]
    parent: IComment;
    getChildren: Function
}

export const Comment:FC<ICommentProps> = observer(({parent,getChildren,data}) => {
    return (
        <ul className="list" key={parent.id}>
                        <li>
                        <div onClick={() => {getChildren(parent.kids,parent.id,data)}}>{parent.by}</div>
                        <div>{parent.text}</div>
                        <div>{dateParser(parent.time)}</div>
                        <div>
                            {parent.children && <RecursiveComponent data={parent.children} getChildren={getChildren} />}
                        </div>
                        </li>
                    </ul>
    )
})


Стейт в котором вызывается рекурсия
import {makeAutoObservable, runInAction} from "mobx";
import {api} from "../apiService/apiService";

export interface IComment {
  id: number;
  kids: number[];
  children?: IComment[];
  parent?: number;
  text: string;
  by: string;
  type: string;
  time: number;
}

class Comments {
  comments: IComment[] | undefined = [];
  status: string = "pending";
  constructor() {
    makeAutoObservable(this);
  }
  async getComments(kids: number[]) {
    const data: IComment[] = [];
    if (kids === undefined) return;
    for (const item of kids) {
      const response = await api.get<IComment>(
        `https://hacker-news.firebaseio.com/v0/item/${item}.json`
      );
      data.push(response);
    }
    runInAction(() => {
      this.comments = data;
      this.status = "done";
    });
  }
  async getCommentsChildren(kids: number[], id: number, children: IComment[]) {
    const data: IComment[] = [];
    if (kids === undefined) return;
    for (const item of kids) {
      const response = await api.get<IComment>(
        `https://hacker-news.firebaseio.com/v0/item/${item}.json`
      );
      data.push(response);
    }
    const recursFunc = (comments:IComment[]) => {
      if(!comments) return;
      for(let i = 0; i < comments.length; i++) {
          comments[i].children = data;
          if(comments[i].kids.length) {
            recursFunc(children);
          }
      }
      return comments;
    }
    runInAction(() => {
      this.comments = recursFunc(children);
    })
  }
  setNullComments () {
    this.comments = [];
  }
}
export default new Comments();
  • Вопрос задан
  • 79 просмотров
Пригласить эксперта
Ответы на вопрос 1
@5465
Проблема возникает из-за рекурсивной функции, которая вызывает себя слишком много раз, что приводит к переполнению стека вызовов.

В вашем коде рекурсия находится внутри функции getCommentsChildren. В этой функции вы вызываете функцию recursFunc для каждого элемента массива children, который, вероятно, является частью объекта data, полученного из api. Однако вы передаете неправильный аргумент в рекурсивный вызов recursFunc, используя переменную children вместо comments. Это приводит к бесконечному циклу, который приводит к переполнению стека вызовов.

Чтобы исправить проблему, вы можете передавать правильный аргумент в рекурсивный вызов recursFunc, используя переменную comments вместо children. Также вам следует добавить условие выхода из рекурсии, чтобы она не продолжалась бесконечно.

Исправленный код функции getCommentsChildren должен выглядеть примерно так:

async getCommentsChildren(kids: number[], id: number, children: IComment[]) {
    const data: IComment[] = [];
    if (kids === undefined) return;
    for (const item of kids) {
      const response = await api.get<IComment>(
        `https://hacker-news.firebaseio.com/v0/item/${item}.json`
      );
      data.push(response);
    }
    const recursFunc = (comments: IComment[]) => {
      if (!comments) return;
      for (let i = 0; i < comments.length; i++) {
        comments[i].children = data;
        if (comments[i].kids.length) {
          recursFunc(comments[i].children);
        }
      }
      return comments;
    };
    runInAction(() => {
      this.comments = recursFunc(children);
    });
  }


Также, обратите внимание на то, что в компоненте RecursiveComponent вы используете data.map, даже если data не является массивом. Это может вызвать ошибку во время выполнения. Вы можете добавить проверку на массив перед использованием map:

const RecursiveComponent: FC<IRecursiveProps> = observer(({ data, getChildren }) => {
  if (!Array.isArray(data)) {
    return null; // or any fallback component or message
  }

  return (
    <div>
      {data.map((parent: any) => {
        return <Comment parent={parent} getChildren={getChildren} data={data} />;
      })}
    </div>
  );
});


Надеюсь, это поможет вам решить проблему!
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы