Javascript 访问旧状态以与useffect react hook中的新状态进行比较,并将其与自定义hook useproval进行比较
我正在尝试将基于类的react组件迁移到react挂钩。该组件的目的是从HackerNews API获取故事,并在每5000毫秒后通过再次点击API获取新数据来进行轮询 我面临的问题是使用下面的自定义钩子来比较我以前的状态和当前状态,并且仅在比较之后执行useffect()中的其他函数 在这里,我很可能缺少一些基本的自定义钩子或useffect()实现 我也跟着 这是完美的工作 问题出在这一行上Javascript 访问旧状态以与useffect react hook中的新状态进行比较,并将其与自定义hook useproval进行比较,javascript,reactjs,react-hooks,Javascript,Reactjs,React Hooks,我正在尝试将基于类的react组件迁移到react挂钩。该组件的目的是从HackerNews API获取故事,并在每5000毫秒后通过再次点击API获取新数据来进行轮询 我面临的问题是使用下面的自定义钩子来比较我以前的状态和当前状态,并且仅在比较之后执行useffect()中的其他函数 在这里,我很可能缺少一些基本的自定义钩子或useffect()实现 我也跟着 这是完美的工作 问题出在这一行上 const fromPrevStoriesIds = usePrevious(prevStorie
const fromPrevStoriesIds = usePrevious(prevStoriesIds);
PrevStoriesIDS中的变量在return()中给了我很好的值,但在useffect()中它没有定义。
import React, { Component, useState, useEffect, useRef } from "react";
import axios from "axios";
import MUIDataTable from "mui-datatables";
import "./Dashboard.css";
import NewItemAddedConfirmSnackbar from "./NewItemAddedConfirmSnackbar";
import TextField from "@material-ui/core/TextField";
import Button from "@material-ui/core/Button";
const isEqual = require("lodash.isequal");
const differenceWith = require("lodash.differencewith");
const omit = require("lodash.omit");
function usePrevious(value) {
const ref = useRef();
useEffect(() => {
ref.current = value;
});
return ref.current;
}
const getEachStoryGivenId = (id, index) => {
return new Promise((resolve, reject) => {
axios
.get(`https://hacker-news.firebaseio.com/v0/item/${id}.json`)
.then(res => {
let story = res.data;
let result = omit(story, ["descendants", "time", "id", "type"]);
if (
result &&
Object.entries(result).length !== 0 &&
result.constructor === Object
) {
resolve(result);
} else {
reject(new Error("No data received"));
}
});
});
};
const Dashboard = () => {
const [prevStoriesIds, setPrevStoriesIds] = useState([]);
const [fetchedData, setFetchedData] = useState([]);
const [isLoading, setIsLoading] = useState(false);
const [tableState, setTableState] = useState({});
const [
openNewItemAddedConfirmSnackbar,
setOpenNewItemAddedConfirmSnackbar
] = useState(false);
const [noOfNewStoryAfterPolling, setNoOfNewStoryAfterPolling] = useState(0);
const [rowsPerPage, setRowsPerPage] = useState(10);
const onChangeRowsPerPage = rowsPerPage => {
setRowsPerPage(rowsPerPage);
};
const closeNewItemConfirmSnackbar = () => {
setOpenNewItemAddedConfirmSnackbar(false);
axios
.get("https://hacker-news.firebaseio.com/v0/newstories.json")
.then(storyIds => {
setPrevStoriesIds(storyIds.data.slice(0, 2));
getAllNewStory(storyIds);
});
};
const getAllNewStory = storyIds => {
setIsLoading(true);
let topStories = storyIds.data.slice(0, 2).map(getEachStoryGivenId);
let results = Promise.all(topStories);
results
.then(res => {
setFetchedData(res);
setIsLoading(false);
})
.catch(err => {
console.log(err);
});
};
const fromPrevStoriesIds = usePrevious(prevStoriesIds);
useEffect(() => {
const fetchData = () => {
axios
.get("https://hacker-news.firebaseio.com/v0/newstories.json")
.then(storyIds => {
// console.log("STORY IDs FETCHED ", storyIds.data.slice(0, 2));
setPrevStoriesIds(storyIds.data.slice(0, 2));
getAllNewStory(storyIds);
});
};
fetchData();
const doPolling = () => {
var timer = setInterval(() => {
axios
.get("https://hacker-news.firebaseio.com/v0/newstories.json")
.then(storyIds => {
console.log(
"fromPrevStoriesIds INSIDE doPolling() ",
fromPrevStoriesIds
);
if (
fromPrevStoriesIds !== undefined &&
!isEqual(fromPrevStoriesIds.sort(), storyIds.data.slice(0, 2).sort())
) {
setPrevStoriesIds(storyIds.data.slice(0, 2));
setNoOfNewStoryAfterPolling(
differenceWith(
prevStoriesIds.sort(),
storyIds.data.slice(0, 2).sort(),
isEqual
).length
);
getAllNewStory(storyIds);
setOpenNewItemAddedConfirmSnackbar(true);
}
});
}, 5000);
};
doPolling();
// return () => {
// console.log("cleaning up");
// clearInterval(timer);
// };
}, [rowsPerPage, noOfNewStoryAfterPolling]);
let renderedStoriesOnPage = [];
const getDataToRender = (() => {
renderedStoriesOnPage = fetchedData.map(i => {
return Object.values(i);
});
return renderedStoriesOnPage;
})();
const columnsOptions = [
{
name: "Author",
sortDirection: tableState
? tableState.columns && tableState.columns[0].sortDirection
: null
},
{
name: "score",
sortDirection: tableState
? tableState.columns && tableState.columns[1].sortDirection
: null
},
{
name: "title",
sortDirection: tableState
? tableState.columns && tableState.columns[2].sortDirection
: null
},
{
name: "URL",
options: {
filter: false,
customBodyRender: (value, tableMeta, updateValue) => {
// console.log("TABLE META IS ", JSON.stringify(tableMeta));
return (
<a target="_blank" href={value}>
{value}
</a>
);
}
}
}
];
const options = {
filter: true,
selectableRows: false,
filterType: "dropdown",
responsive: "stacked",
selectableRows: "multiple",
rowsPerPage: tableState ? tableState.rowsPerPage : 10,
onChangeRowsPerPage: onChangeRowsPerPage,
activeColumn: tableState ? tableState.activeColumn : 0,
onTableChange: (action, tableState) => {
// console.log("taBLE STATE IS ", JSON.stringify(tableState));
setTableState(tableState);
}
};
return (
<React.Fragment>
{console.log("fromPrevStoriesIds INSIDE RETURN --- ", fromPrevStoriesIds)}
<div
style={{
marginLeft: "15px",
marginTop: "80px",
display: "flex",
flexDirection: "row"
}}
>
<h4 style={{ width: "400px", paddingRight: "15px" }}>
Hacker News top 2
</h4>
</div>
<div>
{isLoading ? (
<div className="interactions">
<div className="lds-ring">
<div />
<div />
<div />
<div />
</div>
</div>
) : fetchedData.length !== 0 && renderedStoriesOnPage.length !== 0 ? (
<MUIDataTable
title={"Hacker News API top 2 result"}
data={renderedStoriesOnPage}
columns={columnsOptions}
options={options}
/>
) : null}
<NewItemAddedConfirmSnackbar
openNewItemAddedConfirmSnackbar={openNewItemAddedConfirmSnackbar}
closeNewItemConfirmSnackbar={closeNewItemConfirmSnackbar}
noOfNewStoryAfterPolling={noOfNewStoryAfterPolling}
/>
</div>
</React.Fragment>
);
};
export default Dashboard;
import React,{Component,useState,useffect,useRef}来自“React”;
从“axios”导入axios;
从“mui数据表”导入MUIDataTable;
导入“/Dashboard.css”;
从“/newitemAddedConfigrSnackbar”导入NewitemAddConfigrSnackbar”;
从“@material ui/core/TextField”导入TextField;
从“@物料界面/核心/按钮”导入按钮;
const isEqual=要求(“lodash.isEqual”);
const differenceWith=require(“lodash.differenceWith”);
const omit=要求(“lodash.omit”);
函数usePrevious(值){
const ref=useRef();
useffect(()=>{
参考电流=值;
});
返回参考电流;
}
const getEachStoryGivenId=(id,index)=>{
返回新承诺((解决、拒绝)=>{
axios
.得到(`https://hacker-news.firebaseio.com/v0/item/${id}.json`)
。然后(res=>{
让故事=真实数据;
让结果=省略(故事,[“后代”,“时间”,“id”,“类型]);
如果(
结果&&
Object.entries(result).length!==0&&
result.constructor==对象
) {
决心(结果);
}否则{
拒绝(新错误(“未收到数据”);
}
});
});
};
常量仪表板=()=>{
const[PrevStoriesId,setPrevStoriesId]=useState([]);
常量[fetchedData,setFetchedData]=useState([]);
const[isLoading,setIsLoading]=useState(false);
const[tableState,setTableState]=useState({});
常数[
OpenNewItemAddedConfigrmSnackbar,
SetOpenNewItemAddedConfigrmSnackbar
]=使用状态(假);
const[noOfNewStoryAfterPolling,setNoOfNewStoryAfterPolling]=useState(0);
const[rowsPerPage,setRowsPerPage]=useState(10);
const onChangeRowsPerPage=rowsPerPage=>{
setRowsPerPage(rowsPerPage);
};
const closeNewItemConfirmSnackbar=()=>{
setOpenNewItemAddedConfigrmSnackbar(false);
axios
.get(“https://hacker-news.firebaseio.com/v0/newstories.json")
。然后(StoryID=>{
setPrevStoriesId(storyIds.data.slice(0,2));
getAllNewStory(StoryID);
});
};
const getAllNewStory=storyIds=>{
设置加载(真);
让topStories=storyIds.data.slice(0,2).map(getEachStoryGivenId);
让结果=承诺。全部(顶部);
结果
。然后(res=>{
setFetchedData(res);
设置加载(假);
})
.catch(错误=>{
控制台日志(err);
});
};
const fromPrevStoriesId=usePrevious(PrevStoriesId);
useffect(()=>{
常量fetchData=()=>{
axios
.get(“https://hacker-news.firebaseio.com/v0/newstories.json")
。然后(StoryID=>{
//log(“获取的故事ID”,storyIds.data.slice(0,2));
setPrevStoriesId(storyIds.data.slice(0,2));
getAllNewStory(StoryID);
});
};
fetchData();
常数doPolling=()=>{
变量计时器=设置间隔(()=>{
axios
.get(“https://hacker-news.firebaseio.com/v0/newstories.json")
.then(故事ID=>{
console.log(
“从doPolling()中的PrevStoriesId”,
来自前故事类
);
如果(
fromPrevStoriesId!==未定义&&
!isEqual(fromPrevStoriesId.sort(),StoryId.data.slice(0,2.sort())
) {
setPrevStoriesId(storyIds.data.slice(0,2));
setNoOfNewStoryAfterPolling(
不同于(
PrevStoriesId.sort(),
storyIds.data.slice(0,2).sort(),
等质量
).长度
);
getAllNewStory(StoryID);
setOpenNewItemAddedConfigrmSnackbar(true);
}
});
}, 5000);
};
doPolling();
//return()=>{
//控制台日志(“清理”);
//清除间隔(计时器);
// };
},[rowsPerPage,noOfNewStoryAfterPolling];
让RenderStoriesOnPage=[];
常量getDataToRender=(()=>{
RenderStoriesOnPage=fetchedData.map(i=>{
返回Object.values(i);
});
返回RenderStoriesOnPage;
})();
常数列选项=[
{
姓名:“作者”,
排序方向:表状态
?tableState.columns&&tableState.columns[0]。排序方向
:null
},
{
名称:“得分”,
排序方向:表状态
?tableState.columns&&tableState.columns[1]。排序方向
:null
},
{
姓名:“职务”,
排序方向:表状态
?tableState.columns&&tableState.columns[2]。排序方向
:null
},
{
名称:“URL”,
选项:{
筛选器:false,
customBodyRender:(值、tableMeta、updateValue)=>{
//log(“tableMeta是”,JSON.stringify(tableMeta));
返回(
);
}
}
}
];
常量选项={
过滤器:对,
selectableRows:false,
filterType:“下拉列表”,
响应:“堆叠”,
selectableRows:“多行”,
划船者
import React, { Component, useState, useEffect, useRef } from "react";
import axios from "axios";
import MUIDataTable from "mui-datatables";
import "./Dashboard.css";
import NewItemAddedConfirmSnackbar from "./NewItemAddedConfirmSnackbar";
import TextField from "@material-ui/core/TextField";
import Button from "@material-ui/core/Button";
const isEqual = require("lodash.isequal");
const differenceWith = require("lodash.differencewith");
const omit = require("lodash.omit");
function usePrevious(value) {
const ref = useRef();
useEffect(() => {
ref.current = value;
});
return ref.current;
}
const getEachStoryGivenId = (id, index) => {
return new Promise((resolve, reject) => {
axios
.get(`https://hacker-news.firebaseio.com/v0/item/${id}.json`)
.then(res => {
let story = res.data;
let result = omit(story, ["descendants", "time", "id", "type"]);
if (
result &&
Object.entries(result).length !== 0 &&
result.constructor === Object
) {
resolve(result);
} else {
reject(new Error("No data received"));
}
});
});
};
const Dashboard = () => {
const [prevStoriesIds, setPrevStoriesIds] = useState([]);
const [fetchedData, setFetchedData] = useState([]);
const [isLoading, setIsLoading] = useState(false);
const [tableState, setTableState] = useState({});
const [
openNewItemAddedConfirmSnackbar,
setOpenNewItemAddedConfirmSnackbar
] = useState(false);
const [noOfNewStoryAfterPolling, setNoOfNewStoryAfterPolling] = useState(0);
const [rowsPerPage, setRowsPerPage] = useState(10);
const onChangeRowsPerPage = rowsPerPage => {
setRowsPerPage(rowsPerPage);
};
const closeNewItemConfirmSnackbar = () => {
setOpenNewItemAddedConfirmSnackbar(false);
axios
.get("https://hacker-news.firebaseio.com/v0/newstories.json")
.then(storyIds => {
setPrevStoriesIds(storyIds.data.slice(0, 2));
getAllNewStory(storyIds);
});
};
const getAllNewStory = storyIds => {
setIsLoading(true);
let topStories = storyIds.data.slice(0, 2).map(getEachStoryGivenId);
let results = Promise.all(topStories);
results
.then(res => {
setFetchedData(res);
setIsLoading(false);
})
.catch(err => {
console.log(err);
});
};
const fromPrevStoriesIds = usePrevious(prevStoriesIds);
useEffect(() => {
const fetchData = () => {
axios
.get("https://hacker-news.firebaseio.com/v0/newstories.json")
.then(storyIds => {
// console.log("STORY IDs FETCHED ", storyIds.data.slice(0, 2));
setPrevStoriesIds(storyIds.data.slice(0, 2));
getAllNewStory(storyIds);
});
};
fetchData();
const doPolling = () => {
var timer = setInterval(() => {
axios
.get("https://hacker-news.firebaseio.com/v0/newstories.json")
.then(storyIds => {
console.log(
"fromPrevStoriesIds INSIDE doPolling() ",
fromPrevStoriesIds
);
if (
fromPrevStoriesIds !== undefined &&
!isEqual(fromPrevStoriesIds.sort(), storyIds.data.slice(0, 2).sort())
) {
setPrevStoriesIds(storyIds.data.slice(0, 2));
setNoOfNewStoryAfterPolling(
differenceWith(
prevStoriesIds.sort(),
storyIds.data.slice(0, 2).sort(),
isEqual
).length
);
getAllNewStory(storyIds);
setOpenNewItemAddedConfirmSnackbar(true);
}
});
}, 5000);
};
doPolling();
// return () => {
// console.log("cleaning up");
// clearInterval(timer);
// };
}, [rowsPerPage, noOfNewStoryAfterPolling]);
let renderedStoriesOnPage = [];
const getDataToRender = (() => {
renderedStoriesOnPage = fetchedData.map(i => {
return Object.values(i);
});
return renderedStoriesOnPage;
})();
const columnsOptions = [
{
name: "Author",
sortDirection: tableState
? tableState.columns && tableState.columns[0].sortDirection
: null
},
{
name: "score",
sortDirection: tableState
? tableState.columns && tableState.columns[1].sortDirection
: null
},
{
name: "title",
sortDirection: tableState
? tableState.columns && tableState.columns[2].sortDirection
: null
},
{
name: "URL",
options: {
filter: false,
customBodyRender: (value, tableMeta, updateValue) => {
// console.log("TABLE META IS ", JSON.stringify(tableMeta));
return (
<a target="_blank" href={value}>
{value}
</a>
);
}
}
}
];
const options = {
filter: true,
selectableRows: false,
filterType: "dropdown",
responsive: "stacked",
selectableRows: "multiple",
rowsPerPage: tableState ? tableState.rowsPerPage : 10,
onChangeRowsPerPage: onChangeRowsPerPage,
activeColumn: tableState ? tableState.activeColumn : 0,
onTableChange: (action, tableState) => {
// console.log("taBLE STATE IS ", JSON.stringify(tableState));
setTableState(tableState);
}
};
return (
<React.Fragment>
{console.log("fromPrevStoriesIds INSIDE RETURN --- ", fromPrevStoriesIds)}
<div
style={{
marginLeft: "15px",
marginTop: "80px",
display: "flex",
flexDirection: "row"
}}
>
<h4 style={{ width: "400px", paddingRight: "15px" }}>
Hacker News top 2
</h4>
</div>
<div>
{isLoading ? (
<div className="interactions">
<div className="lds-ring">
<div />
<div />
<div />
<div />
</div>
</div>
) : fetchedData.length !== 0 && renderedStoriesOnPage.length !== 0 ? (
<MUIDataTable
title={"Hacker News API top 2 result"}
data={renderedStoriesOnPage}
columns={columnsOptions}
options={options}
/>
) : null}
<NewItemAddedConfirmSnackbar
openNewItemAddedConfirmSnackbar={openNewItemAddedConfirmSnackbar}
closeNewItemConfirmSnackbar={closeNewItemConfirmSnackbar}
noOfNewStoryAfterPolling={noOfNewStoryAfterPolling}
/>
</div>
</React.Fragment>
);
};
export default Dashboard;
function usePrevious(value) {
const ref = useRef();
useEffect(() => {
ref.current = value;
});
return ref;
}
const fromPrevStoriesIds = usePrevious(prevStoriesIds);
useEffect(() => {
const fetchData = () => {
axios
.get("https://hacker-news.firebaseio.com/v0/newstories.json")
.then(storyIds => {
// console.log("STORY IDs FETCHED ", storyIds.data.slice(0, 2));
setPrevStoriesIds(storyIds.data.slice(0, 2));
getAllNewStory(storyIds);
});
};
fetchData();
const doPolling = () => {
var timer = setInterval(() => {
axios
.get("https://hacker-news.firebaseio.com/v0/newstories.json")
.then(storyIds => {
console.log(
"fromPrevStoriesIds INSIDE doPolling() ",
fromPrevStoriesIds.current
);
if (
fromPrevStoriesIds.current !== undefined &&
!isEqual(fromPrevStoriesIds.current.sort(), storyIds.data.slice(0, 2).sort())
) {
setPrevStoriesIds(storyIds.data.slice(0, 2));
setNoOfNewStoryAfterPolling(
differenceWith(
prevStoriesIds.sort(),
storyIds.data.slice(0, 2).sort(),
isEqual
).length
);
getAllNewStory(storyIds);
setOpenNewItemAddedConfirmSnackbar(true);
}
});
}, 5000);
};
doPolling();
// return () => {
// console.log("cleaning up");
// clearInterval(timer);
// };
}, [rowsPerPage, noOfNewStoryAfterPolling]);