Я пытаюсь создать счетчик посещений, основанный на клике пользователя. Он увеличивает счетчик каждый раз, когда пользователь щелкает. Я бегу Гэтсби JS с реакции.
Я использую лямбда-функцию для сохранения счета в faunadb, поэтому он увеличивается с каждым нажатием кнопки. Это работает.
Для клиентской части я обновляю состояние номера HitCounter компонента с помощью localStorage, поэтому каждый раз, когда нажимается кнопка, я обновляю localStorage.
Все это работает довольно хорошо. Однако, если я изменю состояние StoryPopFull
(см. Код ниже), нажав кнопку закрытия в StoryBlock
, и открою снова, нажав кнопку more, состояние сохранит состояние localStorage, что является хорошим. Однако, если я изменю состояние StoryPop
, закрывая StoryGrid
, снова открою все, что состояние SvgAnimation
(компонент, в котором живет счетчик посещений) берет его из запроса graphQL, теперь это было бы хорошо, если запрос пришел достаточно быстро , но между лямбда, faunadb и нажатием refre sh на странице задержка составляет около 20 секунд, потому что я не использую подписки graphql, поэтому должен быть refre sh вида.
Какое хорошее решение, когда пользователь использует localstorage сайта, чтобы отслеживать счетчик, но когда они возвращают или обновляют sh страницу (не перезагрузка компонента), я могу обновить localstorage с помощью запроса graphql.
Вот мой код, спасибо заранее.
import React, { useState, useEffect } from 'react';
import { Link } from "gatsby"
import Layout from "../components/layout"
import { gql } from "apollo-boost"
import { useQuery } from "@apollo/react-hooks"
import rabbit from "../images/rabbit.svg"
import { StoryBlock, StoryGrid, Svg } from "../components/indexStyles"
class SvgAnimation extends React.Component {
constructor(props) {
super(props)
let initialCount = Number(window.localStorage.getItem('count') || 0)
this.state = {
buttonDisabled: false,
hitCounter: initialCount,
}
this.handleCLick = this.handleCLick.bind(this);
}
componentDidMount(){
const {data} =this.props
window.localStorage.setItem('count', data.findHitCounterByID.amount)
}
async handleCLick(e) {
const {count, loading, data} =this.props
if(this.state.fillAnimate > 0){
try{
const response = await fetch("/.netlify/functions/hitCounter", {
method: "POST",
body: JSON.stringify({test:"test"}),
})
if (!response.ok) {
console.log(response);
}
else{
console.log("succes");
}
} catch(e){ console.log(e)}
let initialCount1 = Number(window.localStorage.getItem('count') || 0)
window.localStorage.setItem('count', initialCount1 +1)
let initialCount = Number(window.localStorage.getItem('count') || 0)
this.setState({ hitCounter: initialCount })
}
}
render() {
const { buttonDisabled, hitCounter } = this.state;
return (
<>
<button disabled={buttonDisabled} onClick={e => { this.handleCLick(e) }}>I want this</button>
<Svg aria-labelledby="title" id="svg" viewBox="0 0 100 125" xmlns="http://www.w3.org/2000/svg">
...
</Svg>
<span>{hitCounter}</span>
</>
)
}
}
const HIT_COUNTER = gql`
query HitCounter{
findHitCounterByID(id: "264173443862233609") {
amount
}
}
`
const IndexPage = () => {
const [StoryPop, setStoryPop] = useState(false);
const [StoryPopFull, setStoryPopFull] = useState(false);
const { loading, data } = useQuery(HIT_COUNTER);
const rabbitClick = (e) => {
setStoryPop(true)
}
const storyClick = (e) => {
setStoryPopFull(true)
}
const clickClose = (e) => {
setStoryPopFull(false)
}
const clickCloseStoryGrid = (e) => {
setStoryPop(false)
setStoryPopFull(false)
}
return (
<Layout>
<img onClick={(e => { rabbitClick(e) })} onMouseOut={e => { imageHoverOut(e) }} src={rabbit} />
{StoryPop &&
<StoryGrid >
<button onClick={e => { clickCloseStoryGrid(e) }}>Close</button>
<button onClick={e => { storyClick(e) }}>More</button>
</StoryGrid>
}
{StoryPopFull &&
<StoryBlock>
<button onClick={e => { clickClose(e) }}>Close</button>
<SvgAnimation count={data.findHitCounterByID.amount} data={data} loading={loading} />
</StoryBlock>
}
</Layout>
)
}
export default IndexPage