Cómo renderizar un nuevo mensaje sin re-rendering mensajes anteriores en react.js?

Estoy tratando de añadir un nuevo mensaje desde el componente form.js en el array de mensajes que está en App.js, y mapear a través de él para renderizar ese mensaje.

Pero cada vez que añado un nuevo mensaje todos los demás mensajes en el array también consiguen re-render, estos mensajes anteriores deben estar en la UI, pero no deben re-render, Debido a esto, crea un problema de rendimiento como si quisiera añadir el mensaje 100 entonces todos los otros 99 mensajes también consiguen re-render con el mensaje 100.

foto de salida no deseada:-

Como se puede ver la imagen de la consola que mapeé a través de la matriz de mensajeArr para renderizar el mensaje 4 pero todos los demás mensajes 1, 2, 3 también conseguir re-render con el mensaje 4. Quiero otros mensajes en la UI pero no deben ser re-render con el mensaje actual que es el mensaje 4

¿Qué debo hacer para mostrar mensajes anteriores con el mensaje actual sin recibir re-render?

App.js

const App = () => {
const [messageArr, setMessageArr] = useState([]);

const addMessage = (messageText) => {
    setMessageArr([...messageArr, messageText]);
};

return (
    
    {messageArr.map(({ id, message }) => (
    {message}
    ))}
);};

Form.js

const Form = ({ addMessage }) => {
const [messageText, setMessageText] = useState('');

const handleSubmit = (e) => {
    e.preventDefault();
    const newMessage = {
        id: v4(),
        message: messageText
    } 
    addMessage(newMessage);
    setMessageText('');
};

return (
    
setMessageText(e.target.value)} />
);}

Pregunta hecha hace 3 años, 4 meses, 25 días - Por pixelpioneer


3 Respuestas:

  • Hay una cosa que puedes hacer.

    Hacer un nuevo componente para un solo mensaje y poner esta línea en ese componente

    import React, { PureComponent } from "react";
    import "./styles.css";
    
    class Message extends PureComponent {
      render() {
        return 
    {this.props.message}
    ; } } export default Message;

    Entonces en su archivo principal usted puede cambiar su regreso a

    return (
        
      {messageArr.map(({ id, message }) => ( ))}
    )

    Ahora ya que el Mensaje es un componente puro, no se reenviará hasta que se cambie su props. Así que sus mensajes antiguos no serán reenviados de nuevo y sólo el nuevo mensaje rendirá.

    Respondida el Dec 21, 2020 a las 05:17 - por codecraftsman

    Votos positivos: 0 | Votos negativos: 0

  • El problema en el código se debe a que estás re-renderizando todos los mensajes anteriores cada vez que se agrega un nuevo mensaje al array. La solución para renderizar solo el nuevo mensaje sin re-renderizar los anteriores es utilizar un enfoque de optimización llamado "Memoization".

    Puedes usar la función React.memo() para envolver el componente de mensaje individual y evitar que se vuelva a renderizar a menos que sus propiedades cambien. De esta forma, otros mensajes anteriores en la UI seguirán siendo mostrados sin re-renderizar.

    Aquí te dejo una solución modificada para tu código:

    jsx
    const Message = React.memo(({ id, message }) => {
      return 
    {message}
    ; }); const App = () => { const [messageArr, setMessageArr] = useState([]); const addMessage = (newMessage) => { setMessageArr([...messageArr, newMessage]); }; return (
      {messageArr.map(({ id, message }) => ( ))}
    ); }; const Form = ({ addMessage }) => { const [messageText, setMessageText] = useState(''); const handleSubmit = (e) => { e.preventDefault(); const newMessage = { id: v4(), message: messageText } addMessage(newMessage); setMessageText(''); }; return ( setMessageText(e.target.value)} /> ); };

    Con esta solución, el componente <Message /> se renderizará solo cuando la propiedad id o message cambien. Los mensajes anteriores en la UI se mantendrán sin re-renderizarse cuando se agregue un nuevo mensaje.

    Respondida el Dec 22, 2020 a las 05:20 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • El problema

    El problema surge porque el estado messageArr en el componente App es mutable. Cada vez que se llama a setMessageArr para agregar un nuevo mensaje, React vuelve a renderizar el componente App y todos sus descendientes. Esto provoca el re-render de todos los mensajes anteriores, incluso si no se han modificado.

    Solución

    Para evitar el re-render innecesario, debemos utilizar un estado inmutable para messageArr. Esto se puede lograr utilizando el operador de propagación (...) para crear una nueva matriz cada vez que se agregua un nuevo mensaje.

    App.js actualizado

    jsx
    const App = () => {
      const [messageArr, setMessageArr] = useState([]);
    
      const addMessage = (messageText) => {
        setMessageArr((prevMessageArr) => [...prevMessageArr, messageText]);
      };
    
      return (
        
      {messageArr.map(({ id, message }) => (
      {message}
      ))}
    ); };

    En el código actualizado, cuando se llama a addMessage, se crea una nueva matriz que incluye el nuevo mensaje mediante el operador de propagación. Esto garantiza que el estado messageArr siga siendo inmutable y React solo vuelva a renderizar los mensajes que se hayan modificado (en este caso, solo el nuevo mensaje).

    Ejemplo de salida deseado

    Después de implementar este cambio, la salida esperada sería la siguiente:

    Como se puede ver en la imagen de la consola que mapeé a través de la matriz de mensajeArr para renderizar el mensaje 4, pero otros mensajes 1, 2, 3 no consiguen re-render con el mensaje 4. Otros mensajes permanecen en la IU sin re-render

    Respondida el Dec 22, 2020 a las 05:20 - por Gemini

    Votos positivos: 0 | Votos negativos: 0