-
I worked on two projects with Chris for Go Free Range, the first of which involved working with a React form to record numbers given by the user. We already had some
<select>elements to do this, e.g.const Form = () => { const [unit, setUnit] = useState(1); const handleUnitChange = ({ target: { value }}) => { setUnit(parseFloat(value)); }; return ( <select value={unit} onChange={handleUnitChange}> <option value="1">m</option> <option value="100">cm</option> <option value="1000">mm</option> </select> ); };This works fine. React is able to interpret our numeric value for
unitand select the appropriate<option>in our dropdown. When the user changes their selection, the corresponding value is passed tohandleUnitChangeand stored as a floating point number. This way, we keep ourunitas a number throughout so it is ready to be passed to other functions without any coercion.However, if we try to do the same thing with an
<input type="text">, we quickly run into trouble:const Form = () => { const [unit, setUnit] = useState(1); const handleUnitChange = ({ target: { value }}) => { setUnit(parseFloat(value)); }; return ( <input type="text" value={unit} onChange={handleUnitChange} /> ); };What happens when the user tries to empty the field (e.g. perhaps to enter a new value from scratch)?
handleUnitChangewill fire with a value of an empty string:> parseFloat("") NaNPerhaps then we try to avoid storing
NaNand instead setunitto beundefinedornullif it is falsy?const handleUnitChange = ({ target: { value }}) => { setUnit(value ? parseFloat(value) : undefined); // or setUnit(value ? parseFloat(value) : null); }If we do this, when the user clears the field, React will log a warning that we’re switching a component from being controlled to being uncontrolled because setting the
valueof a field toundefinedornullhas a special meaning: it tells React this field is now uncontrolled.Given it is totally valid for the user to enter an empty value, we realised we needed to separate our concerns: use strings for the
inputvalue but convert the value to a number when we pass it elsewhere in our application.const Form = () => { const [unit, setUnit] = useState("1"); const handleUnitChange = ({ target: { value }}) => { setUnit(value); }; doSomeCalculation(parseFloat(unit)); return ( <input type="text" value={unit} onChange={handleUnitChange} /> ); }; const doSomeCalculation = (unit) => { if (Number.isNaN(unit)) { return; } // ... };Using an
<input type="number">helps a little with this as it prevents non-numeric inputs firing theonChangeevent but it seemed cleaner to deal with the problem in our logic than rely on browser behaviour. -
The second project Chris and I worked on involved a Python API written with Flask. Getting things running locally was quite a pain with my attempts to use pip to install NumPy ending in compilation errors. In the end, switching to the previous stable Python release of 3.8 (rather than the latest of 3.9) using pyenv solved my problems.
However, I was left with a bit of a mess of installed Homebrew formulae and wanted to clean things up. Thankfully, I found an answer on the macOS Super User with a great tip for removing unused Homebrew dependencies:
$ brew bundle dump $ brew bundle --force cleanupThis will first dump all explicitly installed formulae and casks into a
Brewfile(which you could then edit) and then uninstall anything no longer required. -
I ended up in a similar mess after installing Xcode and
brew doctorreported that I had out-of-date Command Line Tools.Attempting to use
xcode-select --installfailed with a strange error about the software update not being found and Software Update itself couldn’t install the update properly.It turns out that Xcode includes the Command Lines Tools itself even though I had a previous installation in
/Library/Developers/CommandLineToolsinstalled viaxcode-select. I ended up completely removing both Xcode and the Command Line Tools and reinstalling the latter before Software Update could successfully pick up the right update. -
Simon wrote a truly excellent blog post about Rails autoloading with Zeitwerk titled “Rails autoloading — now it works, and how!”. This is a follow-up to his 2013 post “Rails autoloading — how it works, and when it doesn’t” to which I often found myself referring.
-
Following last week’s need for earplugs, I lost some hearing in my left ear. I returned from a trip to the pharmacy with some urea hydrogen peroxide and watched the Great British Bake Off sideways with the deeply unsettling sensation of fizzing in my ear canal.
I woke in the small hours of Thursday morning to find the room uncontrollably spinning around me. I staggered to the bathroom where I discovered I could no longer get my eyes to focus straight ahead without them constantly drifting to my right. With E’s help, I managed to speak to a doctor on the phone and go in to our local GP’s surgery to see someone in person that morning.
After waiting outside, the doctor greeted me at the door wrapped in plastic, said that they needed to “fire [their] gun” (a thermometer) at me and instructed me not to touch anything as we walked to a consultation room.
Thankfully, it’s a viral ear infection that’ll clear up by itself in a matter of days.
-
Now that C is confident enough walking, he happily roams our flat looking for things to prod, pull or combine in some way. We’ve already lost three bowls to his curiosity and I’ve had to rewire one plug. It also means that I took the step of lowering the mattress in his cot now that he more closely resembles the IKEA cartoon for “toddler” than the one for “baby”.
Weeknotes 54
By Paul Mucur,
on