Javascript 当原子状态更新为以前的值时,React反冲选择器不触发其get
我已经开始通过自己的一个快速项目来学习反应和退缩。一个具有按钮的单页网站,简言之,每个按钮进行REST调用,并使用返回的数据创建一个表 单击按钮时,它会更新存储给定按钮URL的atom。选择器被订阅到此atom并触发对API的异步REST请求。从那里,返回的数据被处理到一个表中 在第一次单击每个按钮时,一切都按预期进行。调用特定URL并生成表。问题是,如果再次单击按钮,将显示以前获取的数据。我不确定我是否错过了一个重要的步骤,调试并没有真正向我透露任何信息 原子类别:Javascript 当原子状态更新为以前的值时,React反冲选择器不触发其get,javascript,reactjs,react-state-management,recoiljs,Javascript,Reactjs,React State Management,Recoiljs,我已经开始通过自己的一个快速项目来学习反应和退缩。一个具有按钮的单页网站,简言之,每个按钮进行REST调用,并使用返回的数据创建一个表 单击按钮时,它会更新存储给定按钮URL的atom。选择器被订阅到此atom并触发对API的异步REST请求。从那里,返回的数据被处理到一个表中 在第一次单击每个按钮时,一切都按预期进行。调用特定URL并生成表。问题是,如果再次单击按钮,将显示以前获取的数据。我不确定我是否错过了一个重要的步骤,调试并没有真正向我透露任何信息 原子类别: import {atom}
import {atom} from 'recoil'
export const currentTableState = atom({
key: 'currentTableState',
default: 'Employee',
})
export const currentUrlState = atom({
key: 'currentUrlState',
default: '/employee/find/all?page=0&size=12'
})
export const currentPageState = atom({
key: 'currentPageState',
default: 0
})
export const currentSizeState = atom({
key: 'currentSizeState',
default: 12
})
选择器类别:
import {selector} from "recoil";
import {currentUrlState} from "./atoms";
export const tableData = selector({
key: "currentContactDetails",
get: async ({get}) => {
const response = await fetch(String(get(currentUrlState)));
const json = await response.json();
return json.content;
}
});
包含按钮的NavBar类:
import React from "react";
import './topNavBar.css';
import {useSetRecoilState, useRecoilValue} from "recoil";
import {currentPageState, currentSizeState, currentTableState, currentUrlState} from "../recoil/atoms";
const TopNavBar = () => {
const setCurrentTable = useSetRecoilState(currentTableState);
const setUrl = useSetRecoilState(currentUrlState);
const page = useRecoilValue(currentPageState);
const size = useRecoilValue(currentSizeState);
function updateState(table) {
setCurrentTable(table);
if (table.includes(" ")) {
let split = table.split(" ");
table = split[1] + '/' + split[0];
}
setUrl(`${table.toLowerCase()}/find/all?page=${page}&size=${size}`);
}
return (
<div className='top-nav'>
<button onClick={() => updateState("Employee")}>Employee
</button>
<button onClick={() => updateState("Material")}>Material
</button>
<button onClick={() => updateState("Equipment")}>Equipment
</button>
<button onClick={() => updateState("Material Request")}>Material Request
</button>
<button onClick={() => updateState("Equipment Request")}>Equipment Request
</button>
</div>
)
}
export default TopNavBar;
从“React”导入React;
导入“./topNavBar.css”;
从“反冲”导入{useSetRecoilState,useRecoilValue};
从“./反冲/原子”导入{currentPageState,currentSizeState,currentTableState,currentUrlState};
常量TopNavBar=()=>{
const setCurrentTable=useSetRecoilState(currentTableState);
const setUrl=useSetRecoilState(currentUrlState);
const page=useRecoilValue(currentPageState);
const size=useRecoilValue(currentSizeState);
函数更新属性(表){
可设置电流表;
if(表中包括(“”){
let split=表。split(“”);
表=拆分[1]+'/'+拆分[0];
}
setUrl(`${table.toLowerCase()}/find/all?page=${page}&size=${size}`);
}
返回(
updateState(“雇员”)}>Employee
updateState(“Material”)}>Material
更新不动产(“设备”)}>设备
UpdateEstate(“材料申请”)}>材料申请
updateState(“设备请求”)}>设备请求
)
}
导出默认TopNavBar;
生成表的Table类:
import React from "react";
import './table.css'
import {useRecoilState, useRecoilValueLoadable} from "recoil";
import {currentTableState} from "../recoil/atoms";
import {tableData} from "../recoil/selectors";
const Table = () => {
const [currentTable] = useRecoilState(currentTableState);
const items = useRecoilValueLoadable(tableData);
const Data = () => {
switch (items.state) {
case 'loading':
return <div>Loading...</div>;
case 'hasError':
throw items.contents;
case 'hasValue':
return <ConstructTable items={items.contents}/>
default:
return <div>Something went terribly wrong.</div>
}
}
const TableHeaders = (headers) => <tr>{headers.headers.map(key => <th key={key.toString()}>{key}</th>)}</tr>;
const TableRows = (items) =>
items.items.map(row =>
<tr className='body' key={row.id}>
{Object.values(row).map((cell, cellIndex) => <td key={cellIndex}>{cell}</td>)}
</tr>
)
const ConstructTable = (content) => {
let {items} = content
if (items.length === 0) return <div>{currentTable} table has no data...</div>
else return (
<div className="table">
<table>
<thead>
<tr>
<th
className="table-name"
colSpan={Object.keys(items[0]).length}
>
{currentTable}
</th>
</tr>
<TableHeaders headers={Object.keys(items[0])}/>
</thead>
<tbody>
<TableRows items={items}/>
</tbody>
</table>
</div>
);
}
return <Data/>
}
export default Table;
从“React”导入React;
导入“./table.css”
从“反冲”导入{useRecoilState,useRecoilValueLoadable};
从“./反冲/原子”导入{currentTableState};
从“./反冲/选择器”导入{tableData};
常数表=()=>{
const[currentTable]=useRecoilState(currentTableState);
const items=useRecoilValueLoadable(tableData);
常量数据=()=>{
开关(项目状态){
“装载”案例:
返回装载。。。;
案例“hasError”:
抛出项目.内容;
案例“hasValue”:
返回
违约:
返回:出了严重的问题。
}
}
consttableheaders=(headers)=>{headers.headers.map(key=>{key}});
const TableRows=(项目)=>
items.items.map(行=>
{Object.values(row.map)((单元格,单元格索引)=>{cell}}
)
const ConstructTable=(内容)=>{
设{items}=content
如果(items.length==0)返回{currentTable}表没有数据。。。
否则返回(
{currentTable}
);
}
返回
}
导出默认表;
更新:
我绕过了这个问题,放弃了使用选择器、混合挂钩和原子来获得类似的功能,如:
const url = useRecoilValue(currentUrlState);
const table = useRecoilValue(currentTableState);
const [data, setData] = useRecoilState(currentTableData);
const [requestState, setRequestState] = useState('loading');
useEffect(() => {
console.debug('use effect triggered')
setRequestState('loading');
fetch(String(url))
.then(res => res.json())
.then(
(result) => {
setData(result.content);
setRequestState('loaded');
},
(error) => setRequestState(error.message)
);
}, [url, setData])
const Data = () => {
switch (requestState) {
case 'loading':
return <div>Loading...</div>;
case 'loaded':
return <ConstructTable items={data}/>
default:
return <div>{requestState}</div>
}
}
const url=useRecoilValue(currentUrlState);
const table=useRecoilValue(currentTableState);
const[data,setData]=useRecoilState(currentTableData);
const[requestState,setRequestState]=useState('loading');
useffect(()=>{
console.debug('使用效果已触发')
setRequestState(“加载”);
获取(字符串(url))
.then(res=>res.json())
.那么(
(结果)=>{
setData(结果、内容);
setRequestState('loaded');
},
(错误)=>setRequestState(错误消息)
);
},[url,setData])
常量数据=()=>{
开关(请求状态){
“装载”案例:
返回装载。。。;
“已加载”案例:
返回
违约:
返回{requestState}
}
}
虽然我觉得这并不理想。好吧,我根据您的第一个版本创建了一个沙盒。它似乎工作得很好。 注意:仅启用员工和物料按钮。表数据也与您的不同。但它应该说明这个想法
https://codesandbox.io/s/friendly-wiles-kjpjw?file=/src/Table.js