Javascript 当原子状态更新为以前的值时,React反冲选择器不触发其get

Javascript 当原子状态更新为以前的值时,React反冲选择器不触发其get,javascript,reactjs,react-state-management,recoiljs,Javascript,Reactjs,React State Management,Recoiljs,我已经开始通过自己的一个快速项目来学习反应和退缩。一个具有按钮的单页网站,简言之,每个按钮进行REST调用,并使用返回的数据创建一个表 单击按钮时,它会更新存储给定按钮URL的atom。选择器被订阅到此atom并触发对API的异步REST请求。从那里,返回的数据被处理到一个表中 在第一次单击每个按钮时,一切都按预期进行。调用特定URL并生成表。问题是,如果再次单击按钮,将显示以前获取的数据。我不确定我是否错过了一个重要的步骤,调试并没有真正向我透露任何信息 原子类别: import {atom}

我已经开始通过自己的一个快速项目来学习反应和退缩。一个具有按钮的单页网站,简言之,每个按钮进行REST调用,并使用返回的数据创建一个表

单击按钮时,它会更新存储给定按钮URL的atom。选择器被订阅到此atom并触发对API的异步REST请求。从那里,返回的数据被处理到一个表中

在第一次单击每个按钮时,一切都按预期进行。调用特定URL并生成表。问题是,如果再次单击按钮,将显示以前获取的数据。我不确定我是否错过了一个重要的步骤,调试并没有真正向我透露任何信息

原子类别:

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