У меня есть сетка, которая при нажатии на плитку отображает выпадающий список. Я извлекаю содержимое из локального файла JSON, который я создал. Плитка создается для каждого объекта в файле JSON.
в файле JSON, у меня есть свойство isActive
- по умолчанию оно false
, затем при нажатии оно меняется на true
.
[
{
"title": "title one",
"body": "Lorem ipsum dolor sit amet consectetur adipisicing elit. Quam, voluptate",
"isActive": false,
"image": {
"src": "/images/Cinco-de-Mayo_2-600x436.jpg",
"alt": "some text"
},
"cta": {
"text": "Learn more",
"link": "https://reactjs.org/",
"open": true
}
}
]
ПРОВАЙДЕР КОНТЕКСТА:
import React, { Component, createContext } from 'react';
export const TileContext = createContext();
export class TileProvider extends Component {
state = {
tileShowCount: 4,
loading: true,
tiles: [],
handleDropDown: (id) => {
this.setState(prevState => ({
tiles: prevState.tiles.map((tile, i) => ({
...tile,
isActive: ( id === i ) ? !this.state.tiles[id].isActive : false
}))
}));
},
handleDropDownKeyPress: (id, e) => {
if(e.key === 'Enter'){
this.setState(prevState => ({
tiles: prevState.tiles.map((tile, i) => ({
...tile,
isActive: ( id === i ) ? !this.state.tiles[id].isActive : false
}))
}));
}
},
fetchData: async (url) => {
let res = await fetch(url)
let data = await res.json();
return data
},
loadMore: () => {
this.setState( prevState => {
return {
tileShowCount: prevState.tileShowCount += 4
}
})
}
}
componentDidMount() {
this.state.fetchData('/data/tileInfo.json')
.then((res) => {
this.setState( prevState => {
return {
tiles: res.slice(0, this.state.tileShowCount),
loading: false
}
});
})
.catch((err) => {console.log(err);})
}
componentDidUpdate(prevProps, prevState) {
console.log('prevstate:', prevState.tileShowCount, 'currentstate:', this.state.tileShowCount);
if(prevState.tiles !== this.state.tiles) {
this.state.fetchData('/data/tileInfo.json')
.then((res) => {
this.setState( prevState => {
return {
tiles: res.slice(0, this.state.tileShowCount),
loading: false
}
});
})
.catch((err) => {console.log(err);})
}
}
render() {
return (
<TileContext.Provider value={{...this.state}}>
{this.props.children}
</TileContext.Provider>
);
}
}
У меня есть две проблемы с этим:
1: componentDidUpdate()
продолжает отправлять запрос на JSON файл. Я проверил вкладку сети в chrome Dev tools и увидел, что она зацикливается.
2: Каждый раз, когда я нажимаю на плитку, она открывается, а затем немедленно снова закрывает плитку, потому что запрос на выборку Файл JSON сбрасывает свойство isActive
обратно в исходное состояние: false
По сути, я пытаюсь загружать больше плиток, когда вы нажимаете кнопку «Загрузить еще». Итак, я использую метод slice
для извлечения начальных 4 плиток из массива JSON. Затем при нажатии «загрузить еще» будет обновлен метод slice
, чтобы извлечь еще 8 фрагментов из файла JSON.
ЗАГРУЗИТЬ БОЛЬШЕ КОМПОНЕНТА:
Функция loadMore
увеличивает число на 8 при нажатии. Затем обновляется tileShowCount
в поставщике контекста. Затем tileShowCount
используется в методе slice
для обновления свойства tiles
в состоянии.
const TileLoadMore = () => {
const {loadMore} = useContext(TileContext);
return (
<Fragment>
<button className="tile-load-more"
onClick={() => {
loadMore();
}}>
Load more</button>
</Fragment>
);
}
FETCH CALL:
componentDidUpdate(prevProps, prevState) {
console.log('prevstate:', prevState.tileShowCount, 'currentstate:', this.state.tileShowCount);
if(prevState.tiles !== this.state.tiles) {
this.state.fetchData('/data/tileInfo.json')
.then((res) => {
this.setState( prevState => {
return {
tiles: res.slice(0, this.state.tileShowCount),
loading: false
}
});
})
.catch((err) => {console.log(err);})
}
}
Вот ссылка на мой проект: https://codesandbox.io/s/tiles-load-more-o2ub5
Заранее спасибо :)