Как передать состояние из дочернего в основной?
Я только недавно начал изучать реакт, поэтому тухлыми помидорами в меня прошу не кидаться, а просто дать дельную подсказку. Делаю страницу Блога. У меня есть основной Blog.tsx, где находятся все компоненты. И есть компонент Filter , в котором находятся кнопки по переключению тематики(которые я отмэпил и отфлитровал исходя из тематик всех, которые есть в массиве объектов) Так же в Filter прописана логика, по которой фильтруются посты блога.
Мне нужно, filtred вот отсюда (находится в компоненте Filter)
const [filtred, setFiltred] = useState(posts)
передать в Blog.tsx, чтобы пробежаться мэпом уже по filtred, а не по изначальному posts.
Как это можно реализовать?
Куски кода Blog.tsx
import React from "react";
import './Blog.scss'
import {Post} from "./components/Post/Post";
import {Best} from "./components/Best/Best";
import {Filter} from "./components/Filter/Filter";
interface Props {
}
export const Blog = () => {
return (
<div className='background__blog'>
<div className='container'>
<div className='blog__title'>Блог</div>
<div className='blog__content'>
<div className='content__posts'>{filtred.map((post) => <Post post={post} key={post.id}/>)}</div>
<div className='content__panel'>
<div className='panel__filter'>
<div className='filter__text'>Фильтр по тематике</div>
<Filter />
</div>
<div className='panel__best'><Best/></div>
</div>
</div>
</div>
</div>
);
};
Filter.tsx
import React, {useState} from 'react';
import {posts} from "../../../../data/Posts";
interface Props {
}
export const Filter = () => {
const [filtred, setFiltred] = useState(posts)
function ArrFilter(Themes: string) {
if (Themes === 'all') {
setFiltred(posts)
} else {
let newArr = [...posts].filter(post => post.Themes === Themes)
setFiltred(newArr)
}
}
const FillArr: {[Themes: string]: number} = {};
const fill = posts.filter(({Themes}) => (!FillArr[Themes] && (FillArr[Themes] = 1)));
return (
<div className='filter__btn'>
<button onClick={() => ArrFilter('all')}>Все</button>
<>{fill.map((FillArr) =><button onClick={() => ArrFilter(FillArr.Themes)}>{FillArr.Themes}</button>)}</>
</div>
);
};
{posts} - массив объектов с постами.
Ответы (1 шт):
В Blog.tsx добавляете функцию
const getNewFilter = (filter: TypeFiltered) => {
// Получен новый фильтр, обрабатывайте
}
и передаем ее в компонент Filter
<Filter change={getNewFilter} />
в Filter.tsx Указываете пропс и обработчик события, например useEffect, что бы отслеживать изменение состояния filrted
export const Filter = ({ change }: { change: (newFilter) => void }) => {
useEffect(() => {
change(filtred);
}, [filtred]);
change: (newFilter) => void - Вот это по хорошему должно выглядеть так change: (newFilter: TypeFiltered) => void где TypeFiltered это описанный тип для filtred. с функцией getNewFilter аналогично.
Работать это будет так: Дочерний компонент, будет вызывать переданную функцию, а исполняться она будет в родительском компмоненте.