don't re-compute values on first render (unnecessary, values are part of state)
This commit is contained in:
parent
174bab79e4
commit
2d0deca127
14 changed files with 274 additions and 115 deletions
|
|
@ -2,21 +2,11 @@ import { apply, assignFn, getSymbol, getType, NotAFunctionError, symbolFunction,
|
|||
|
||||
import { Editor, type EditorState } from "./Editor";
|
||||
import { Value } from "./Value";
|
||||
import type { Dynamic, SetStateFn, State2Props } from "./util/extra";
|
||||
import { DeepError, type ResolvedType, type SetStateFn, type State2Props } from "./types";
|
||||
|
||||
import { useEffect } from "react";
|
||||
import "./CallBlock.css";
|
||||
|
||||
export class DeepError {
|
||||
e: Error;
|
||||
depth: number;
|
||||
constructor(e, depth) {
|
||||
this.e = e;
|
||||
this.depth = depth;
|
||||
}
|
||||
};
|
||||
|
||||
type ResolvedType = Dynamic | DeepError | undefined;
|
||||
import { useEffectBetter } from "./util/use_effect_better";
|
||||
|
||||
export interface CallBlockState<
|
||||
FnState=EditorState,
|
||||
|
|
@ -34,6 +24,26 @@ interface CallBlockProps<
|
|||
> extends State2Props<CallBlockState<FnState,InputState>,EditorState> {
|
||||
}
|
||||
|
||||
export function resolveCallBlock(fn: ResolvedType, input: ResolvedType) {
|
||||
if (have(input) && have(fn)) {
|
||||
try {
|
||||
const outputResolved = apply(input)(fn); // may throw
|
||||
return outputResolved; // success
|
||||
}
|
||||
catch (e) {
|
||||
if (!(e instanceof UnifyError) && !(e instanceof NotAFunctionError)) {
|
||||
throw e;
|
||||
}
|
||||
return new DeepError(e, 0); // eval error
|
||||
}
|
||||
}
|
||||
else if (input instanceof DeepError) {
|
||||
return input; // bubble up the error
|
||||
}
|
||||
else if (fn instanceof DeepError) {
|
||||
return new DeepError(fn.e, fn.depth+1);
|
||||
}
|
||||
}
|
||||
|
||||
function have(resolved: ResolvedType) {
|
||||
return resolved && !(resolved instanceof DeepError);
|
||||
|
|
@ -50,35 +60,13 @@ function headlessCallBlock({state, setState}: CallBlockProps) {
|
|||
const setResolved = (callback: SetStateFn<ResolvedType>) => {
|
||||
setState(state => ({...state, resolved: callback(state.resolved)}));
|
||||
}
|
||||
useEffect(() => {
|
||||
|
||||
useEffectBetter(() => {
|
||||
// Here we do something spooky: we update the state in response to state change...
|
||||
// The reason this shouldn't give problems is because we update the state in such a way that the changes only 'trickle up', rather than getting stuck in a cycle.
|
||||
if (have(input.resolved) && have(fn.resolved)) {
|
||||
try {
|
||||
const outputResolved = apply(input.resolved)(fn.resolved); // may throw
|
||||
setResolved(() => outputResolved); // success
|
||||
}
|
||||
catch (e) {
|
||||
if (!(e instanceof UnifyError) && !(e instanceof NotAFunctionError)) {
|
||||
throw e;
|
||||
}
|
||||
setResolved(() => new DeepError(e, 0)); // eval error
|
||||
}
|
||||
}
|
||||
else if (input.resolved instanceof DeepError) {
|
||||
setResolved(() => input.resolved); // bubble up the error
|
||||
}
|
||||
else if (fn.resolved instanceof DeepError) {
|
||||
setResolved(() => {
|
||||
// @ts-ignore
|
||||
return new DeepError(fn.resolved.e, fn.resolved.depth+1);
|
||||
}); // bubble up the error
|
||||
}
|
||||
else {
|
||||
// no errors and at least one is undefined:
|
||||
setResolved(() => undefined); // chill out
|
||||
}
|
||||
}, [input.resolved, fn.resolved]);
|
||||
setResolved(() => resolveCallBlock(fn.resolved, input.resolved));
|
||||
}, [fn.resolved, input.resolved]);
|
||||
|
||||
const onFnCancel = () => {
|
||||
setState(state => state.input); // we become our input
|
||||
}
|
||||
|
|
@ -109,7 +97,9 @@ export function CallBlock({ state, setState }: CallBlockProps) {
|
|||
/>
|
||||
{/* Output (or Error) */}
|
||||
{ state.resolved instanceof DeepError && state.resolved.e.toString()
|
||||
|| state.resolved && <><Value dynamic={state.resolved} />☑</>}
|
||||
|| state.resolved && <><Value dynamic={state.resolved} />
|
||||
{/* ☑ */}
|
||||
</>}
|
||||
</div>
|
||||
</div>
|
||||
</span>;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue