Quiero mostrar un div relacionado con una propiedad de objeto que se vuelve verdadero o falso. Y usé una forma, pero no estoy seguro de que sea la mejor o si abre los problemas de rendimiento.
Estoy comprobando esa propiedad en el ciclo que en la sección de retorno para evitar una operación de matriz adicional. Pero creo que causará un render extra.
La otra opción es registrar esa propiedad fuera de la sección de devolución. Pero esto será causa de una operación de matriz adicional.
¿Cuál es la mejor manera para mí? Mostré 2 implementaciones diferentes a continuación.
Opción 1:
const RadioButtonList: FunctionComponent<RadioButtonListProps> = ({ items, changeFilter }) => { const [showClearIcon, setShowClearIcon] = React.useState(false); return ( <div className="radio-button-list"> {showClearIcon && <div className="clear-icon">clear</div>} <ul> {items.map(item => { /* this is the area what I'm checking the property */ if (item.selected) { setShowClearIcon(true); } return ( <li key={item.id}> <label htmlFor={item.text} className="radio"> <span className="input"> <input type="radio" onClick={changeFilter} readOnly /> </span> </label> </li> ); })} </ul> </div> ); };Opcion 2:
const RadioButtonList: FunctionComponent<RadioButtonListProps> = ({ items, changeFilter }) => { const [showClearIcon, setShowClearIcon] = React.useState(false); /* set in useEffect hook */ useEffect(() => { if(items.some(item => item.selected)) { setShowClearIcon(true); } }, [items]); return ( <div className="radio-button-list"> {showClearIcon && <div className="clear-icon">clear</div>} <ul> {items.map(item => { return ( <li key={item.id}> <label htmlFor={item.text} className="radio"> <span className="input"> <input type="radio" onClick={changeFilter} readOnly /> </span> </label> </li> ); })} </ul> </div> ); };Parece que showClearIcon no necesita ser un átomo de estado en absoluto, sino solo un valor memorizado que depende de los items .
const showClearIcon = React.useMemo( () => items.some(item => item.selected), [items], );La opción 1 pone en cola una actualización de estado en el retorno de representación, no la use.
Utilice la opción 2 para poner en cola correctamente la actualización como efecto secundario. En React, la función render debe considerarse una función pura. No ponga en cola incondicionalmente las actualizaciones de estado.
En cuanto al rendimiento, iterar una matriz es O(n) . Iterar una matriz dos veces sigue siendo O(n) .
El "estado" showClearIcon probablemente no debería ser el estado Reaccionar, ya que se deriva fácilmente de los items prop.
Identificar la representación mínima (pero completa) del estado de la interfaz de usuario
Repasemos cada uno y descubramos cuál es el estado. Haga tres preguntas sobre cada dato:
- ¿Se transmite de un padre a través de accesorios? Si es así, probablemente no sea estatal.
- ¿Se mantiene invariable con el tiempo? Si es así, probablemente no sea estatal.
- ¿Puede calcularlo en función de cualquier otro estado o accesorios en su componente? Si es así, no es estatal.
Debido a esto, simplemente calcule el valor showClearIcon localmente.
const showClearIcon = items.some(item => item.selected); Esto se puede memorizar con el useMemo dependiendo de los items si es necesario.
Técnicamente, puede hacerlo sin useState y useEffect y sin iterar sobre la matriz dos veces, consulte el ejemplo a continuación ( puede que no sea necesario, pero es bueno saber que esto también es posible ):
const RadioButtonList: FunctionComponent<RadioButtonListProps> = ({ items, changeFilter, }) => { const renderItems = () => { let showClearIcon = false; let markup = ( <ul> {items.map((item) => { if (item.selected) { showClearIcon = true; } return ( <li key={item.id}> <label htmlFor={item.text} className="radio"> <span className="input"> <input type="radio" onClick={changeFilter} readOnly /> </span> </label> </li> ); })} </ul> ); return ( <> {showClearIcon && <div className="clear-icon">clear</div>} {markup} </> ); }; return <div className="radio-button-list">{renderItems()}</div>; };Simplemente creó una función que genera el marcado.