如何在不重新渲染之前的消息的情况下渲染新消息?

时间:2020-12-19 11:33:14

标签: reactjs react-redux react-router

我正在尝试将来自 form.js 组件的新消息添加到 App.js 中的消息数组中,并通过它映射以呈现该消息。

但是每次我添加一条新消息时,数组中的所有其他消息也会重新渲染,由于这些,它会产生性能问题,好像我想添加第 100 条消息,然后所有其他 99 条消息也会重新渲染 -使用第 100 条消息进行渲染。

不需要的输出照片:-

As you can see the console image I mapped over through the messageArr array to render message 4 but all other messages 1, 2, 3 also getting render with message 4 I want other messages on UI but they should not get re-render with the current message which is message 4

是否有任何解决方案,例如只渲染添加的消息?

App.js

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

const addMessage = (messageText) => {
    setMessageArr([...messageArr, messageText]);
};
return (
    <div>
        <ul>
            {messageArr.map(({ id, message }) => (
                <div key={id}>
                    <li>{message}</li>
                    {console.log(message)}
                </div>
            ))}
        </ul>
        <Form addMessage={addMessage} />
    </div>
)};

Form.js

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

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

return (
    <form onSubmit={handleSubmit}>
        <input
            type='text'
            value={messageText}
            onChange={(e) => setMessageText(e.target.value)}
        />
        <button>Add message</button>
    </form>
)};

3 个答案:

答案 0 :(得分:1)

这行得通!

在 React 中,只有当 Child 中的 shoudComponentUpdate 返回 true 时,才会在 Parent 重新渲染时重新渲染 Child,默认情况下为 true。 (谈论基于类的孩子) 所以,我建议:

  1. 为消息项创建一个单独的组件
  2. 实现 shouldComponentUpdate,它接收 nextProps 作为参数
  3. 比较nextProps:如果它们与当前的props相同,则返回false,否则返回true
  4. 这样,只会呈现新消息

同样重要的是:不要忘记 key

答案 1 :(得分:0)

因为 setMessageArr([...messageArr, messageText]); 正在添加新消息但不会删除以前的消息。您需要做的就是:setMessageArr([messageText]);

编辑:console.log(message) 显示多条消息,您正在正确设置值,但没有正确测试这些值。无论何时您想要测试某个值(您想要查看的更新值)使用 useEffect 测试更改,在您的情况下是这样的:

useEffect(()=>{
console.log(messageArr)
  },[messageArr]);

不要在这里和那里为任何值做console.log,而是将它放在useEffect中。当你这样做时你会看到正确的结果,从App.js的div部分删除console.log和按照我建议的方式测试。

答案 2 :(得分:0)

v4() 函数是做什么的?我认为问题可能是它是一个随机值生成器,所以每次消息数据发生变化时,都会更改密钥并使 react 重新渲染之前的所有消息。

如果是这种情况,请尝试使用消息 ID 作为您的密钥,以便如果添加了新消息,react 将识别前一条消息的 id 并且不会重新渲染先前呈现的消息

{messageArr.map((message) => (
  <div key={message.id}>
    <li key={message.id}>{message}</li>
  </div>
))}