@dualdeazz

Как обновлять стейт с бесконечно вложенным списом?

У меня есть рекурсивный компонент
import React, {FC, ReactNode} from 'react';
import {dateParser} from "../utils/dateParser";

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

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

export default RecursiveComponent;


И стейт
import {makeAutoObservable, runInAction} from "mobx";
import {api} from "../apiService/apiService";

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

class Comments {
    comments:IComment[] = [];
    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) {
        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 = this.comments.map((comment:any) => {
                if(comment.id === id) {
                    return {...comment,children: data};
                }
                return comment;
            });
        })
    }
}
export default new Comments();

При клике на заголовок отправляется запрос и подгружаются вложенные комментарии, если во вложенном комментарии есть еще вложенные, они так же подгружаются, но мой код не работает, и подгружается только первая вложенность. В чем прчичина и как обновлять стейт с бесконечно вложенным списком?
  • Вопрос задан
  • 98 просмотров
Пригласить эксперта
Ответы на вопрос 1
Alexandroppolus
@Alexandroppolus
кодир
this.comments = this.comments.map(...)

этот map обходит только верхний уровень комментов. Соответственно, если id принадлежит какому-то вложенному комменту, он просто не найдется.

Надо перебирать рекурсивно все комменты, чтобы отыскать по id. А как найдешь, просто выставить в нем поле children, и завершить рекурсию
foundComment.children = data;

эта твоя замена с помощью map - очень дурацкая идея, много лишних перерисовок, не "mobx-way"

для полноты картины отметим ещё, что в комплект к RecursiveComponent надо бы отдельный компонент для комментария, и оба эти компонента обернуть в observer. Тогда будет всё как задумано великим чуваком - автором mobx.

а если комментов совсем дохрена (например, тысячи), то стоит подумать об их быстром поиске с помощью Map
Ответ написан
Ваш ответ на вопрос

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

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