cleaner pattern
This commit is contained in:
Vendored
+60
-58
@@ -1116,7 +1116,7 @@ var require_react_development = __commonJS({
|
|||||||
var dispatcher = resolveDispatcher();
|
var dispatcher = resolveDispatcher();
|
||||||
return dispatcher.useCallback(callback2, deps);
|
return dispatcher.useCallback(callback2, deps);
|
||||||
}
|
}
|
||||||
function useMemo(create, deps) {
|
function useMemo2(create, deps) {
|
||||||
var dispatcher = resolveDispatcher();
|
var dispatcher = resolveDispatcher();
|
||||||
return dispatcher.useMemo(create, deps);
|
return dispatcher.useMemo(create, deps);
|
||||||
}
|
}
|
||||||
@@ -1887,7 +1887,7 @@ var require_react_development = __commonJS({
|
|||||||
exports.useImperativeHandle = useImperativeHandle;
|
exports.useImperativeHandle = useImperativeHandle;
|
||||||
exports.useInsertionEffect = useInsertionEffect;
|
exports.useInsertionEffect = useInsertionEffect;
|
||||||
exports.useLayoutEffect = useLayoutEffect;
|
exports.useLayoutEffect = useLayoutEffect;
|
||||||
exports.useMemo = useMemo;
|
exports.useMemo = useMemo2;
|
||||||
exports.useReducer = useReducer2;
|
exports.useReducer = useReducer2;
|
||||||
exports.useRef = useRef3;
|
exports.useRef = useRef3;
|
||||||
exports.useState = useState;
|
exports.useState = useState;
|
||||||
@@ -36589,6 +36589,22 @@ var useStore = (options) => {
|
|||||||
const store = (0, import_react2.useContext)(StoreContext);
|
const store = (0, import_react2.useContext)(StoreContext);
|
||||||
return (options == null ? void 0 : options.store) || store || getDefaultStore();
|
return (options == null ? void 0 : options.store) || store || getDefaultStore();
|
||||||
};
|
};
|
||||||
|
var Provider = ({
|
||||||
|
children,
|
||||||
|
store
|
||||||
|
}) => {
|
||||||
|
const storeRef = (0, import_react2.useRef)();
|
||||||
|
if (!store && !storeRef.current) {
|
||||||
|
storeRef.current = createStore();
|
||||||
|
}
|
||||||
|
return (0, import_react2.createElement)(
|
||||||
|
StoreContext.Provider,
|
||||||
|
{
|
||||||
|
value: store || storeRef.current
|
||||||
|
},
|
||||||
|
children
|
||||||
|
);
|
||||||
|
};
|
||||||
var isPromiseLike2 = (x) => typeof (x == null ? void 0 : x.then) === "function";
|
var isPromiseLike2 = (x) => typeof (x == null ? void 0 : x.then) === "function";
|
||||||
var use = import_react2.default.use || ((promise) => {
|
var use = import_react2.default.use || ((promise) => {
|
||||||
if (promise.status === "pending") {
|
if (promise.status === "pending") {
|
||||||
@@ -36668,36 +36684,33 @@ function useAtom(atom2, options) {
|
|||||||
|
|
||||||
// src/Picker.tsx
|
// src/Picker.tsx
|
||||||
var import_jsx_runtime3 = __toESM(require_jsx_runtime(), 1);
|
var import_jsx_runtime3 = __toESM(require_jsx_runtime(), 1);
|
||||||
function create$Picker({ $options = atom([]), $isLoading = atom(false), $selectedOption = atom(""), $url = atom(""), $isEnabled = atom(true) }) {
|
function Picker({ $options, $isLoading, $url, $isEnabled, $selectedOption }) {
|
||||||
return atom({
|
$options = $options || (0, import_react3.useMemo)(() => atom([]), []);
|
||||||
$options,
|
$isLoading = $isLoading || (0, import_react3.useMemo)(() => atom(true), []);
|
||||||
$isLoading,
|
$isEnabled = $isEnabled || (0, import_react3.useMemo)(() => atom(true), []);
|
||||||
$selectedOption,
|
$selectedOption = $selectedOption || (0, import_react3.useMemo)(() => atom(""), []);
|
||||||
$url,
|
const url = useAtomValue($url);
|
||||||
Picker: () => {
|
const options = useAtomValue($options);
|
||||||
const [url, setUrl] = useAtom($url);
|
const isLoading = useAtomValue($isLoading);
|
||||||
const [options, setOptions2] = useAtom($options);
|
const [selectedOption, setSelectedOption] = useAtom($selectedOption);
|
||||||
const [isLoading, setIsLoading] = useAtom($isLoading);
|
const isEnabled = useAtomValue($isEnabled);
|
||||||
const [selectedOption, setSelectedOption] = useAtom($selectedOption);
|
const optionsFetched = useSetAtom((0, import_react3.useMemo)(() => atom(null, (get, set2, options2) => {
|
||||||
const [isEnabled, setIsEnabled] = useAtom($isEnabled);
|
set2($options, options2);
|
||||||
(0, import_react3.useEffect)(() => {
|
set2($isLoading, false);
|
||||||
if (isEnabled) {
|
}), [$options, $isLoading]));
|
||||||
fetch(url).then((x) => x.json()).catch((err) => ["AAPL", "MSFT", "GOOG"]).then((underlyings_) => {
|
(0, import_react3.useEffect)(() => {
|
||||||
setOptions2(underlyings_);
|
if (isEnabled) {
|
||||||
setIsLoading(false);
|
fetch(url).then((x) => x.json()).catch((err) => ["AAPL", "MSFT", "GOOG"]).then(optionsFetched);
|
||||||
});
|
|
||||||
}
|
|
||||||
}, [isEnabled, url]);
|
|
||||||
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { children: isLoading ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: "Loading..." }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("select", { value: selectedOption, onChange: (e) => {
|
|
||||||
setSelectedOption(e.target.value);
|
|
||||||
}, children: [
|
|
||||||
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: "" }, ""),
|
|
||||||
options.map(
|
|
||||||
(date) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: date, children: date }, date)
|
|
||||||
)
|
|
||||||
] }) });
|
|
||||||
}
|
}
|
||||||
});
|
}, [url, isEnabled]);
|
||||||
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Provider, { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { children: isLoading ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: "Loading..." }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("select", { value: selectedOption, onChange: (e) => {
|
||||||
|
setSelectedOption(e.target.value);
|
||||||
|
}, children: [
|
||||||
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: "" }, ""),
|
||||||
|
options.map(
|
||||||
|
(date) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: date, children: date }, date)
|
||||||
|
)
|
||||||
|
] }) }) });
|
||||||
}
|
}
|
||||||
|
|
||||||
// src/App.module.css
|
// src/App.module.css
|
||||||
@@ -36710,50 +36723,39 @@ var App_module_default = {
|
|||||||
var import_jsx_runtime4 = __toESM(require_jsx_runtime(), 1);
|
var import_jsx_runtime4 = __toESM(require_jsx_runtime(), 1);
|
||||||
var baseUrl = "http://127.0.0.1:8234";
|
var baseUrl = "http://127.0.0.1:8234";
|
||||||
var $underlyingsUrl = atom(`${baseUrl}/option_quotes/underlyings`);
|
var $underlyingsUrl = atom(`${baseUrl}/option_quotes/underlyings`);
|
||||||
var $underlyingPicker = create$Picker({ $url: $underlyingsUrl });
|
var $selectedUnderlying = atom("");
|
||||||
var $quoteDatePicker = create$Picker({
|
var $quoteDatePickerUrl = atom((get) => `${baseUrl}/option_quotes/${get($selectedUnderlying)}/quote_dates`);
|
||||||
$url: atom((get) => `${baseUrl}/option_quotes/${get(get($underlyingPicker).$selectedOption)}/quote_dates`),
|
var $isQuoteDatePickerEnabled = atom((get) => get($selectedUnderlying) !== "");
|
||||||
$isEnabled: atom((get) => get(get($underlyingPicker).$selectedOption) !== "")
|
var $selectedQuoteDate = atom("");
|
||||||
});
|
var $strikePickerUrl = atom((get) => `${baseUrl}/option_quotes/${get($selectedUnderlying)}/${get($selectedQuoteDate)}/strikes`);
|
||||||
var $strikePicker = create$Picker({
|
var $isStrikePickerEnabled = atom((get) => get($selectedQuoteDate) !== "" && get($selectedUnderlying) !== "");
|
||||||
$url: atom((get) => `${baseUrl}/option_quotes/${get(get($underlyingPicker).$selectedOption)}/${get(get($quoteDatePicker).$selectedOption)}/strikes`),
|
var $selectedStrike = atom("");
|
||||||
$isEnabled: atom((get) => get(get($quoteDatePicker).$selectedOption) !== "" && get(get($underlyingPicker).$selectedOption) !== "")
|
var $frontMonthExpirationPickerUrl = atom((get) => `${baseUrl}/option_quotes/${get($selectedUnderlying)}/${get($selectedQuoteDate)}/expirations`);
|
||||||
});
|
var $isFrontMonthExpirationPickerEnabled = atom((get) => get($selectedQuoteDate) !== "" && get($selectedUnderlying) !== "");
|
||||||
var $frontMonthPicker = create$Picker({
|
var $backMonthExpirationPickerUrl = atom((get) => `${baseUrl}/option_quotes/${get($selectedUnderlying)}/${get($selectedQuoteDate)}/expirations`);
|
||||||
$url: atom((get) => `${baseUrl}/option_quotes/${get(get($underlyingPicker).$selectedOption)}/${get(get($quoteDatePicker).$selectedOption)}/expirations`),
|
var $isBackMonthExpirationPickerEnabled = atom((get) => get($selectedQuoteDate) !== "" && get($selectedUnderlying) !== "");
|
||||||
$isEnabled: atom((get) => get(get($quoteDatePicker).$selectedOption) !== "" && get(get($underlyingPicker).$selectedOption) !== "")
|
|
||||||
});
|
|
||||||
var $backMonthPicker = create$Picker({
|
|
||||||
$url: atom((get) => `${baseUrl}/option_quotes/${get(get($underlyingPicker).$selectedOption)}/${get(get($quoteDatePicker).$selectedOption)}/expirations`),
|
|
||||||
$isEnabled: atom((get) => get(get($quoteDatePicker).$selectedOption) !== "" && get(get($underlyingPicker).$selectedOption) !== "")
|
|
||||||
});
|
|
||||||
function App() {
|
function App() {
|
||||||
const { Picker: UnderlyingPicker } = useAtomValue($underlyingPicker);
|
|
||||||
const { Picker: QuoteDatePicker } = useAtomValue($quoteDatePicker);
|
|
||||||
const { Picker: StrikePicker } = useAtomValue($frontMonthPicker);
|
|
||||||
const { Picker: FrontMonthPicker } = useAtomValue($frontMonthPicker);
|
|
||||||
const { Picker: BackMonthPicker } = useAtomValue($backMonthPicker);
|
|
||||||
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: App_module_default.app, children: [
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: App_module_default.app, children: [
|
||||||
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Header_default, {}),
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Header_default, {}),
|
||||||
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: App_module_default.picker, children: [
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: App_module_default.picker, children: [
|
||||||
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("label", { children: "Underlying" }),
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("label", { children: "Underlying" }),
|
||||||
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(UnderlyingPicker, {})
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Picker, { $url: $underlyingsUrl, $selectedOption: $selectedUnderlying })
|
||||||
] }),
|
] }),
|
||||||
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: App_module_default.picker, children: [
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: App_module_default.picker, children: [
|
||||||
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("label", { children: "Quote Date" }),
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("label", { children: "Quote Date" }),
|
||||||
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(QuoteDatePicker, {})
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Picker, { $url: $quoteDatePickerUrl, $isEnabled: $isQuoteDatePickerEnabled, $selectedOption: $selectedQuoteDate })
|
||||||
] }),
|
] }),
|
||||||
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: App_module_default.picker, children: [
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: App_module_default.picker, children: [
|
||||||
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("label", { children: "Strike" }),
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("label", { children: "Strike" }),
|
||||||
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(StrikePicker, {})
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Picker, { $url: $strikePickerUrl, $isEnabled: $isStrikePickerEnabled, $selectedOption: $selectedStrike })
|
||||||
] }),
|
] }),
|
||||||
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: App_module_default.picker, children: [
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: App_module_default.picker, children: [
|
||||||
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("label", { children: "Front Expiration" }),
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("label", { children: "Front Expiration" }),
|
||||||
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(FrontMonthPicker, {})
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Picker, { $url: $frontMonthExpirationPickerUrl, $isEnabled: $isFrontMonthExpirationPickerEnabled })
|
||||||
] }),
|
] }),
|
||||||
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: App_module_default.picker, children: [
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: App_module_default.picker, children: [
|
||||||
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("label", { children: "Back Expiration" }),
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("label", { children: "Back Expiration" }),
|
||||||
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(BackMonthPicker, {})
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Picker, { $url: $backMonthExpirationPickerUrl, $isEnabled: $isBackMonthExpirationPickerEnabled })
|
||||||
] }),
|
] }),
|
||||||
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(HistoricalImpliedVolatilityChart, {})
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(HistoricalImpliedVolatilityChart, {})
|
||||||
] });
|
] });
|
||||||
|
|||||||
+22
-30
@@ -1,7 +1,7 @@
|
|||||||
import Header from './Header';
|
import Header from './Header';
|
||||||
import { HistoricalImpliedVolatilityChart } from "./HistoricalImpliedVolatilityChart";
|
import { HistoricalImpliedVolatilityChart } from "./HistoricalImpliedVolatilityChart";
|
||||||
import { create$Picker } from './Picker';
|
import { Picker } from './Picker';
|
||||||
import { atom as $, useAtomValue } from 'jotai';
|
import { atom as $ } from 'jotai';
|
||||||
//import './index.css';
|
//import './index.css';
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
import k from './App.module.css';
|
import k from './App.module.css';
|
||||||
@@ -10,39 +10,31 @@ const baseUrl = 'http://127.0.0.1:8234';
|
|||||||
|
|
||||||
/* The following are wrapped in atoms to prevent re-creating them if App() re-runs. */
|
/* The following are wrapped in atoms to prevent re-creating them if App() re-runs. */
|
||||||
const $underlyingsUrl = $(`${baseUrl}/option_quotes/underlyings`);
|
const $underlyingsUrl = $(`${baseUrl}/option_quotes/underlyings`);
|
||||||
const $underlyingPicker = create$Picker({$url:$underlyingsUrl});
|
const $selectedUnderlying = $('');
|
||||||
const $quoteDatePicker = create$Picker({
|
|
||||||
$url: $((get) => `${baseUrl}/option_quotes/${get(get($underlyingPicker).$selectedOption)}/quote_dates`),
|
const $quoteDatePickerUrl = $((get) => `${baseUrl}/option_quotes/${get($selectedUnderlying)}/quote_dates`);
|
||||||
$isEnabled: $((get) => get(get($underlyingPicker).$selectedOption)!=='')
|
const $isQuoteDatePickerEnabled = $((get) => get($selectedUnderlying)!=='');
|
||||||
});
|
const $selectedQuoteDate = $('');
|
||||||
const $strikePicker = create$Picker({
|
|
||||||
$url: $((get) => `${baseUrl}/option_quotes/${get(get($underlyingPicker).$selectedOption)}/${get(get($quoteDatePicker).$selectedOption)}/strikes`),
|
const $strikePickerUrl = $((get) => `${baseUrl}/option_quotes/${get($selectedUnderlying)}/${get($selectedQuoteDate)}/strikes`);
|
||||||
$isEnabled: $((get) => get(get($quoteDatePicker).$selectedOption)!=='' && get(get($underlyingPicker).$selectedOption)!=='')
|
const $isStrikePickerEnabled = $((get) => get($selectedQuoteDate)!=='' && get($selectedUnderlying)!=='');
|
||||||
});
|
const $selectedStrike = $('');
|
||||||
const $frontMonthPicker = create$Picker({
|
|
||||||
$url: $((get) => `${baseUrl}/option_quotes/${get(get($underlyingPicker).$selectedOption)}/${get(get($quoteDatePicker).$selectedOption)}/expirations`),
|
const $frontMonthExpirationPickerUrl = $((get) => `${baseUrl}/option_quotes/${get($selectedUnderlying)}/${get($selectedQuoteDate)}/expirations`);
|
||||||
$isEnabled: $((get) => get(get($quoteDatePicker).$selectedOption)!=='' && get(get($underlyingPicker).$selectedOption)!=='')
|
const $isFrontMonthExpirationPickerEnabled = $((get) => get($selectedQuoteDate)!=='' && get($selectedUnderlying)!=='');
|
||||||
});
|
|
||||||
const $backMonthPicker = create$Picker({
|
const $backMonthExpirationPickerUrl = $((get) => `${baseUrl}/option_quotes/${get($selectedUnderlying)}/${get($selectedQuoteDate)}/expirations`);
|
||||||
$url: $((get) => `${baseUrl}/option_quotes/${get(get($underlyingPicker).$selectedOption)}/${get(get($quoteDatePicker).$selectedOption)}/expirations`),
|
const $isBackMonthExpirationPickerEnabled = $((get) => get($selectedQuoteDate)!=='' && get($selectedUnderlying)!=='');
|
||||||
$isEnabled: $((get) => get(get($quoteDatePicker).$selectedOption)!=='' && get(get($underlyingPicker).$selectedOption)!=='')
|
|
||||||
});
|
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
const {Picker:UnderlyingPicker} = useAtomValue($underlyingPicker);
|
|
||||||
const {Picker:QuoteDatePicker} = useAtomValue($quoteDatePicker);
|
|
||||||
const {Picker:StrikePicker} = useAtomValue($frontMonthPicker);
|
|
||||||
const {Picker:FrontMonthPicker} = useAtomValue($frontMonthPicker);
|
|
||||||
const {Picker:BackMonthPicker} = useAtomValue($backMonthPicker);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={k.app}>
|
<div className={k.app}>
|
||||||
<Header />
|
<Header />
|
||||||
<div className={k.picker}><label>Underlying</label><UnderlyingPicker /></div>
|
<div className={k.picker}><label>Underlying</label><Picker $url={$underlyingsUrl} $selectedOption={$selectedUnderlying} /></div>
|
||||||
<div className={k.picker}><label>Quote Date</label><QuoteDatePicker /></div>
|
<div className={k.picker}><label>Quote Date</label><Picker $url={$quoteDatePickerUrl} $isEnabled={$isQuoteDatePickerEnabled} $selectedOption={$selectedQuoteDate}/></div>
|
||||||
<div className={k.picker}><label>Strike</label><StrikePicker /></div>
|
<div className={k.picker}><label>Strike</label><Picker $url={$strikePickerUrl} $isEnabled={$isStrikePickerEnabled} $selectedOption={$selectedStrike}/></div>
|
||||||
<div className={k.picker}><label>Front Expiration</label><FrontMonthPicker /></div>
|
<div className={k.picker}><label>Front Expiration</label><Picker $url={$frontMonthExpirationPickerUrl} $isEnabled={$isFrontMonthExpirationPickerEnabled} /></div>
|
||||||
<div className={k.picker}><label>Back Expiration</label><BackMonthPicker /></div>
|
<div className={k.picker}><label>Back Expiration</label><Picker $url={$backMonthExpirationPickerUrl} $isEnabled={$isBackMonthExpirationPickerEnabled} /></div>
|
||||||
<HistoricalImpliedVolatilityChart />
|
<HistoricalImpliedVolatilityChart />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
+49
-39
@@ -1,44 +1,54 @@
|
|||||||
import { useEffect } from "react";
|
import { useEffect, useMemo } from "react";
|
||||||
import { atom as $, useAtom, Atom, PrimitiveAtom } from 'jotai';
|
import { atom as $, useAtom, Atom, PrimitiveAtom, useAtomValue, useSetAtom, Provider } from 'jotai';
|
||||||
|
|
||||||
type PickerInput = { $options?:PrimitiveAtom<Array<string>>, $isLoading?:PrimitiveAtom<boolean>, $selectedOption?:PrimitiveAtom<string>, $url:Atom<string>, $isEnabled?:Atom<boolean> };
|
type PickerInput = {
|
||||||
export function create$Picker({ $options=$([]), $isLoading=$(false), $selectedOption=$(''), $url=$(''), $isEnabled=$(true) }: PickerInput){
|
$options?:PrimitiveAtom<Array<string>>,
|
||||||
return $({
|
$isLoading?:PrimitiveAtom<boolean>,
|
||||||
$options,
|
$selectedOption?:PrimitiveAtom<string>,
|
||||||
$isLoading,
|
$url:Atom<string>,
|
||||||
$selectedOption,
|
$isEnabled?:Atom<boolean>
|
||||||
$url,
|
};
|
||||||
Picker: ()=>{
|
export function Picker({ $options, $isLoading, $url, $isEnabled, $selectedOption }: PickerInput){
|
||||||
const [url, setUrl] = useAtom($url);
|
$options = $options || useMemo(()=>$([]),[]);
|
||||||
const [options, setOptions] = useAtom($options);
|
$isLoading = $isLoading || useMemo(()=>$(true),[]);
|
||||||
const [isLoading, setIsLoading] = useAtom($isLoading);
|
$isEnabled = $isEnabled || useMemo(()=>$(true),[]);
|
||||||
const [selectedOption, setSelectedOption] = useAtom($selectedOption);
|
$selectedOption = $selectedOption || useMemo(()=>$(''),[]);
|
||||||
const [isEnabled, setIsEnabled] = useAtom($isEnabled);
|
|
||||||
|
|
||||||
useEffect(()=>{
|
const url = useAtomValue($url);
|
||||||
if(isEnabled){
|
const options = useAtomValue($options);
|
||||||
fetch(url)
|
const isLoading = useAtomValue($isLoading);
|
||||||
.then(x=>x.json())
|
const [selectedOption, setSelectedOption] = useAtom($selectedOption);
|
||||||
.catch((err)=>['AAPL', 'MSFT', 'GOOG'])
|
const isEnabled = useAtomValue($isEnabled);
|
||||||
.then((underlyings_)=>{ setOptions(underlyings_); setIsLoading(false); })
|
|
||||||
}
|
|
||||||
},[isEnabled, url])
|
|
||||||
|
|
||||||
return (
|
const optionsFetched = useSetAtom(useMemo(()=>$(null, (get,set,options)=>{
|
||||||
<div>
|
set($options, options);
|
||||||
{isLoading
|
set($isLoading, false);
|
||||||
?
|
}),[$options, $isLoading]));
|
||||||
<span>Loading...</span>
|
|
||||||
:
|
useEffect(()=>{
|
||||||
<select value={selectedOption} onChange={(e)=>{ setSelectedOption(e.target.value); }}>
|
if(isEnabled){
|
||||||
<option key="" value=""></option>
|
fetch(url)
|
||||||
{options.map((date)=>
|
.then(x=>x.json())
|
||||||
<option key={date} value={date}>{date}</option>
|
.catch((err)=>['AAPL', 'MSFT', 'GOOG'])
|
||||||
)}
|
.then(optionsFetched)
|
||||||
</select>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
});
|
},[url, isEnabled])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Provider>
|
||||||
|
<div>
|
||||||
|
{isLoading
|
||||||
|
?
|
||||||
|
<span>Loading...</span>
|
||||||
|
:
|
||||||
|
<select value={selectedOption} onChange={(e)=>{ setSelectedOption(e.target.value); }}>
|
||||||
|
<option key="" value=""></option>
|
||||||
|
{options.map((date)=>
|
||||||
|
<option key={date} value={date}>{date}</option>
|
||||||
|
)}
|
||||||
|
</select>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</Provider>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user