Digamos que tenemos componente:
let Component = (props)=><div>Hi</div>;A veces me he encontrado con un código en el que alguien llama a un componente de reacción como función en el renderizado:
const App = () => ( <div> {Component()} </div> )vs renderizarlo como elemento
const App = () => ( <div> <Component/> </div> )En ganchos de reacción, ¿cuáles son los posibles inconvenientes de llamar al componente como función ?
Hay una pregunta similar , pero no está dirigida específicamente a los ganchos; también esa pregunta es más sobre el rendimiento.
Aquí hay algunas implicaciones de llamar al componente como función frente a representarlo como elemento.
Cuando llama a un componente como una función (vea TestB() a continuación) y contiene el uso de ganchos dentro de él , en ese caso, reacciona cree que los ganchos dentro de esa función pertenecen al componente principal . Ahora, si renderiza condicionalmente ese componente ( TestB() ), violará una de las reglas de los ganchos. Verifique el ejemplo a continuación, haga clic en el botón volver a procesar para ver el error:
Error: se generaron menos ganchos de los esperados. Esto puede deberse a una declaración de devolución anticipada accidental.
function TestB() { let [B, setB] = React.useState(0); return ( <div onClick={() => { setB(B + 1); }} > counter B {B} </div> ); } function App() { let [A, setA] = React.useState(0); return ( <div> <button onClick={() => { setA(A + 1); }} > re-render </button> {/* Conditionally render TestB() */} {A % 2 == 0 ? TestB() : null} </div> ); } ReactDOM.render( <App />, document.getElementById("react") ); <script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script> <div id="react"></div> Ahora puede usar <TestB/> en su lugar y ver la diferencia.
Cuando representa un componente de reacción como elemento de reacción, diga <TestB/> y luego, en el próximo procesamiento, representa un componente diferente <TestC/> en lugar de él (en el mismo lugar en la jerarquía de componentes), debido al algoritmo de reconciliación (y dado que el tipo de componente ha cambiado ), reaccionar desmontará <TestB/> (todo su estado desaparecerá) y montará un nuevo componente <TestC/> en su lugar.
Sin embargo, si lo llama como función (por ejemplo TestB() ), el tipo de componente ya no participará en la reconciliación y es posible que no obtenga los resultados esperados:
function TestB() { return ( <div > <input/> </div> ); } function TestC() { console.log("TestC") return ( <div > <input/> </div> ); } function App() { let [A, setA] = React.useState(0); return ( <div> <button onClick={() => { setA(A + 1); }} > re-render </button> {/* Here we are alternating rendering of components */} {A % 2 == 0 ? TestB() : TestC()} </div> ); } ReactDOM.render( <App />, document.getElementById("react") ); <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script> <div id="react"></div>TestC , pero la entrada muestra el mismo valor que escribió antes, lo que podría no ser lo que desea ya que representó un componente diferente. Esto sucedió porque el algoritmo de reconciliación de React no pudo detectar que nos movimos a un componente diferente (de TestB a TestC ) y no eliminamos la instancia de entrada anterior de DOM. Representa estos componentes como elementos ahora ( <TestB/> y <TestC/> ) para ver la diferencia.