From 680746e3d53b51893c018c29a0c6a16a5e4e13fa Mon Sep 17 00:00:00 2001 From: Joseph Hale Date: Mon, 23 Jun 2025 08:37:11 -0700 Subject: [PATCH] perf: Optimize `BinaryDigit` Unrolls the digit into a static four or six dot column. Combined with an updated `useBinaryTime` hook which preserves object references at the bit level (where possible), now only the dots which change with the new time get rerendered. As a result, typical full render times are below 5ms. When a time update affects multiple digits render times can occasionally climb to ~12ms. --- src/components/BinaryDigit.tsx | 53 +++++++++++++++++++++++++--------- src/utils/useBinaryTime.ts | 17 ++++++++--- 2 files changed, 53 insertions(+), 17 deletions(-) diff --git a/src/components/BinaryDigit.tsx b/src/components/BinaryDigit.tsx index 8bea9ff..831aeb1 100644 --- a/src/components/BinaryDigit.tsx +++ b/src/components/BinaryDigit.tsx @@ -4,7 +4,7 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. -import {StyleSheet, Text, View} from 'react-native'; +import {StyleSheet, View} from 'react-native'; import BinaryDot from './BinaryDot'; import React from 'react'; @@ -25,21 +25,48 @@ const DEFAULTS = { const BinaryDigit: React.FC = args => { const props = {...DEFAULTS, ...args}; + if (props.digit.bits.length === 4) { + return ; + } else if (props.digit.bits.length === 6) { + return ; + } else { + throw new Error(`Invalid digit length: ${props.digit.bits.length}`); + } +}; + +const FourDigit: React.FC = props => { + const settings = { + brightness: props.brightness, + roundness: props.roundness, + showHints: props.showHints, + }; + return ( + + + + + + + + + ); +}; + +const SixDigit: React.FC = props => { + const settings = { + brightness: props.brightness, + roundness: props.roundness, + showHints: props.showHints, + }; return ( - {props.digit.bits.map((bit, idx) => ( - - ))} - {props.showHints && ( - {props.digit.value} - )} + + + + + + ); diff --git a/src/utils/useBinaryTime.ts b/src/utils/useBinaryTime.ts index 3a930d8..c14b6e1 100644 --- a/src/utils/useBinaryTime.ts +++ b/src/utils/useBinaryTime.ts @@ -1,6 +1,7 @@ -import { useState, useEffect } from "react"; -import { BinaryTimeMode, asBinaryTime } from "./binaryTime"; -import { useTime } from "./useTime"; +import {useState, useEffect} from 'react'; +import {BinaryTimeMode, asBinaryTime} from './binaryTime'; +import {useTime} from './useTime'; +import isEqual from 'lodash/isEqual'; export function useBinaryTime( mode: BinaryTimeMode = BinaryTimeMode.SINGLE_DIGITS, @@ -14,8 +15,16 @@ export function useBinaryTime( prev.map((digit, idx) => { if (digit.value === newDigits[idx].value) { return digit; + } else { + // Where possible, preserve object references on a per-bit basis. + return { + value: newDigits[idx].value, + bits: digit.bits.map((bit, bitIdx) => { + const newBit = newDigits[idx].bits[bitIdx]; + return isEqual(bit, newBit) ? bit : newBit; + }), + }; } - return newDigits[idx]; }), ); }, [time, mode]); -- 2.51.2