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
|
|
@ -1,31 +1,39 @@
|
|||
import { useContext, useEffect, useRef } from "react";
|
||||
import { Editor, type EditorState } from "./Editor";
|
||||
import { EnvContext } from "./EnvContext";
|
||||
import type { Dynamic, State2Props } from "./util/extra";
|
||||
import { DeepError, type ResolvedType, type State2Props } from "./types";
|
||||
import { growEnv } from "dope2";
|
||||
import { autoInputWidth } from "./util/dom_trickery";
|
||||
|
||||
import "./LetInBlock.css";
|
||||
import { useEffectBetter } from "./util/use_effect_better";
|
||||
|
||||
export interface LetInBlockState {
|
||||
kind: "let";
|
||||
name: string;
|
||||
value: EditorState;
|
||||
inner: EditorState;
|
||||
resolved: undefined | Dynamic;
|
||||
resolved: ResolvedType;
|
||||
}
|
||||
|
||||
interface LetInBlockProps extends State2Props<LetInBlockState> {
|
||||
}
|
||||
|
||||
export function makeInnerEnv(env, name: string, value: ResolvedType) {
|
||||
if (value && !(value instanceof DeepError)) {
|
||||
return growEnv(env)(name)(value)
|
||||
}
|
||||
return env;
|
||||
}
|
||||
|
||||
export function LetInBlock({state, setState}: LetInBlockProps) {
|
||||
const {name, value, inner} = state;
|
||||
const env = useContext(EnvContext);
|
||||
const innerEnv = makeInnerEnv(env, name, value.resolved);
|
||||
const nameRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
const setInner = inner => setState(state => ({...state, inner}));
|
||||
const setValue = value => setState(state => ({...state, value}));
|
||||
const setInner = callback => setState(state => ({...state, inner: callback(state.inner)}));
|
||||
const setValue = callback => setState(state => ({...state, value: callback(state.value)}));
|
||||
|
||||
const onChangeName = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setState(state => ({...state, name: e.target.value}));
|
||||
|
|
@ -35,10 +43,14 @@ export function LetInBlock({state, setState}: LetInBlockProps) {
|
|||
nameRef.current?.focus();
|
||||
}, []);
|
||||
|
||||
useEffect(() => autoInputWidth(nameRef, name), [nameRef, name]);
|
||||
useEffectBetter(() => {
|
||||
// bubble up
|
||||
setState(state => ({...state, resolved: inner.resolved}));
|
||||
}, [inner.resolved])
|
||||
|
||||
useEffect(() => autoInputWidth(nameRef, name, 60), [nameRef, name]);
|
||||
|
||||
|
||||
const innerEnv = (name !== '') && value.resolved
|
||||
&& growEnv(env)(name)(value.resolved) || env;
|
||||
return <span className="letIn">
|
||||
<div className="decl">
|
||||
<span className="keyword">let</span>
|
||||
|
|
@ -46,7 +58,7 @@ export function LetInBlock({state, setState}: LetInBlockProps) {
|
|||
ref={nameRef}
|
||||
className='editable'
|
||||
value={name}
|
||||
placeholder="<variable name>"
|
||||
placeholder="<name>"
|
||||
onChange={onChangeName}
|
||||
/>
|
||||
<span className="keyword">=</span>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue