don't re-compute values on first render (unnecessary, values are part of state)

This commit is contained in:
Joeri Exelmans 2025-05-14 06:46:03 +02:00
parent 174bab79e4
commit 2d0deca127
14 changed files with 274 additions and 115 deletions

View file

@ -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>