-
-
Save trueadm/35f083d32e5af93dd8fd706dae378123 to your computer and use it in GitHub Desktop.
const React = require("react"); | |
const Lifecycles = React.createLifecycleEvents({ | |
didMount({ setState }) { | |
setState({ | |
disabled: false, | |
}); | |
}, | |
didUpdate({ inputRef }) { | |
if (document.activeElement !== inputRef.value) { | |
inputRef.value.focus(); | |
} | |
} | |
}); | |
// pass in initial state | |
const State = React.createState({ | |
disabled: true, | |
text: "", | |
}); | |
function TextboxView(props) { | |
const inputRef = React.createRef(); | |
return ( | |
<State> | |
{(state, setState) => ( | |
<Lifecycles inputRef={inputRef} setState={setState}> | |
<input | |
{...props} | |
ref={inputRef} | |
disabled={state.disabled} | |
onChange={e => setState({text: e.target.value})} | |
value={state.text} | |
/> | |
</Lifecycles> | |
)} | |
</State> | |
); | |
} |
const React = require("react"); | |
const Lifecycles = React.createLifecycleEvents({ | |
componentDidMount({ setState }) { | |
setState({ | |
disabled: false, | |
}); | |
}, | |
componentDidUpdate({ inputRef }) { | |
if (document.activeElement !== inputRef.value) { | |
inputRef.value.focus(); | |
} | |
} | |
}); | |
const State = React.createState({ | |
disabled: true, | |
text: "", | |
}); | |
function ListView() { | |
const inputRef = React.createRef(); | |
// "adopt" could be sugar syntax for React's callReturn functionality | |
const { state, setState } = adopt <State />; | |
return ( | |
<Lifecycles inputRef={inputRef} setState={setState}> | |
<input | |
ref={inputRef} | |
disabled={state.disabled} | |
onChange={e => setState({text: e.target.value})} | |
value={state.text} | |
/> | |
</Lifecycles> | |
) | |
} |
Cool but isn't this what recompose tries to do?
What would adopt <State />
compile to?
@streamich It's like await
expansion. Every adopt
statement creates new function scope.
function ListView() {
const inputRef = React.createRef();
return (
<State>
{({ state, setState }) => (
<Lifecycles inputRef={inputRef} setState={setState}>
<input
ref={inputRef}
disabled={state.disabled}
onChange={e => setState({text: e.target.value})}
value={state.text}
/>
</Lifecycles>
)}
</State>
);
}
@lmatteis Not quite. It's what react-powerplug tries to do.
-
Tricky one. One approach might be for the update check to compare the
value
of a ref object, but that would be a special case. Another might be to put thee ref in the state. -
You would store
ResizeObserver
in state, just as you would with other "instance variables". -
getDerivedStateFromProps
andshouldComponentUpdate
could be done like:
const State = React.createState({ lastProps: null });
function MyComponent(props) {
const shouldUpdate = ({lastProps}) => shallowCheck(lastProps, props);
const deriveState = () => ({lastProps: props});
const { state, setState } = adopt <State shouldUpdate={shouldUpdate} deriveState={deriveState} />;
// ... rest of code
}
Look like code similar to reason-react ideas
I implemented a very basic POC for #2, using Reacts error bounds: https://codesandbox.io/embed/rr1838zvqm I'm guessing this will also more or less be the way in which suspense can read out fetchers (?), like Dan showed us in his talk.
Looks really nice. However we need to consider more cases.
didUpdate
will be triggered on every render. Is it what we expect?ResizeObserver
instance if we create it indidMount
and should disconnect it inwillUnmount
?getDerivedStateFromProps
andshouldComponentUpdate
?adopt
syntax. If I understand correctly it works likeawait
.