React/react hooks:子组件在状态改变后不重新渲染? [英] React/react hooks: child component is not re-rendering after the state is changed?

查看:362
本文介绍了React/react hooks:子组件在状态改变后不重新渲染?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在用 react/react 钩子编写代码,尝试执行以下操作.

从父组件获取一个对象数组作为prop使用 useState 钩子将其设置为状态.根据预期的过滤器(时间和评级)对状态进行排序,并重新渲染子组件.我看到的是,下面的代码在排序后更新了状态,但是即使状态更新了,依赖于该状态的子组件也不会重新渲染.我认为子组件会在状态改变时自动重新渲染?

import React, {useState} from 'react';从'./ProfilePostspreview'导入ProfilePostspreview;功能简介导航(道具){const [newarray, setnewarray]=useState(props.parray);//'parray' 对象作为 props 传递并保存为 'newarray' 状态const otc = () =>{//按时间排序状态并设置新状态的函数让 k=newarray;setnewarray(k.sort((a, b) => (a.time > b.time) ? -1 : 1 ));}const orc = () =>{//按等级对状态进行排序,然后按时间排序并设置新状态的功能让 k=newarray;setnewarray(k.sort((a, b) => (a.rating > b.rating) ? -1 : (a.rating === b.rating) ? ((a.time > b.time) ? -1 : 1) : 1 ));}返回 (<div><div className="sm_options">//触发otc和orc函数的组件<div className="sm_button" id="order_t" onClick={otc}>按时间排序</div><div className="sm_button" id="order_r" onClick={orc}>按评分排序</div>

<div className="posts_preview_columns_p">//这取决于newarray"状态,但即使在状态被排序和更新后也不会重新渲染?{newarray.map(na=><ProfilePostspreviewpostThumbnail={na.photolink}评分={na.rating}时间={na.time}目标={na.target}/>)}

);}导出默认的 ProfileNavigation;

这可能是什么原因?代码是否有问题,或者对状态进行排序是否被认为不足以让 React 重新渲染子组件?如果是后者,如何在排序后强制重新渲染?

有什么建议吗?谢谢!

解决方案

数组::排序

<块引用>

sort() 方法对数组元素进行原地排序返回排序后的数组.默认排序顺序是升序,内置将元素转换为字符串,然后比较它们的UTF-16 代码单元值的序列.

这对您来说意味着存储在数组中的元素的顺序可能会改变,但数组是原位排序的,这意味着返回相同的数组引用(与返回 new 的其他数组函数不同)数组).

React 协调通过检查 state 和 props 发生,并做出一个整体假设,如果下一个 state/prop 引用没有改变,那么值也没有改变,因此返回最后计算的渲染 DOM.这是更新反应状态的重要细节……每次更新都需要引用一个新对象.

在您的情况下,您只是保存状态中对当前数组的引用,对其进行变异并重新保存.由于引用是稳定的并且不会改变,所以 React 不会重新渲染.

const otc = () =>{让 k = 新数组;//<-- 保存的数组引用!!setnewarray(k.sort((a, b) => (a.time > b.time) ? -1 : 1 ));}

正确的反应方式是将当前数组值复制到一个数组,这样它就会有一个新的对象引用.

const otc = () =>{const newSortedArray = [...newArray].sort((a, b) =>(a.time > b.time) ?-1 : 1);//将旧数组值分散到新数组中,然后排序setNewArray(newSortedArray);}

I am writing a code in react/react hooks that attempt to do the following.

Get an array of objects from the parent component as a prop Set it as a state using useState hook. Sort the state according to the intended filters (Time and Rating), and re-render the child component. What I see is that the below code updates the state after sorting, but even though the state is updated, the child component that is dependent on the state would not re-render. I thought the child component would automatically re-render whenever the state is changed?

import React, {useState} from 'react';
import ProfilePostspreview from './ProfilePostspreview';

function ProfileNavigation(props){
   const [newarray, setnewarray]=useState(props.parray);   //'parray' object passed as props and saved as 'newarray' state    
   const otc = () => {  //Function to sort the state by time and set a new state
       let k=newarray;
       setnewarray(k.sort((a, b) => (a.time > b.time) ? -1 : 1 ));
   }
   const orc = () => {  //Function to sort the state by rating and then time and set a new state
       let k=newarray;
       setnewarray(k.sort((a, b) => (a.rating > b.rating) ? -1 : (a.rating === b.rating) ? ((a.time > b.time) ? -1 : 1) : 1 ));
   }

return (
   <div>
      <div className="sm_options">    //Component to trigger the otc and orc functions
          <div className="sm_button" id="order_t" onClick={otc}>Sort by time</div>    
          <div className="sm_button" id="order_r" onClick={orc}>Sort by rating</div>    
      </div>
      <div className="posts_preview_columns_p"> //This is dependent on the 'newarray' state but is not re-rendering even after the state is sorted and updated?
      {newarray.map(na=>
      <ProfilePostspreview
          postThumbnail={na.photolink}
          rating={na.rating}
          time={na.time}
          target={na.target}
      />
      )}
      </div>
   </div>
);
}

export default ProfileNavigation;

What might be the reason for this? Is there something wrong with the code, or is sorting the state not considered powerful enough for React to re-render the child component? If latter is the case, what can be done to force re-render after sorting?

Any advice? Thanks!

解决方案

array::sort

The sort() method sorts the elements of an array in place and returns the sorted array. The default sort order is ascending, built upon converting the elements into strings, then comparing their sequences of UTF-16 code units values.

What this means for you is the order of elements stored in an array may change, but the array is sorted in place which means the same array reference is returned (unlike other array functions that return new arrays).

React reconciliation occurs by examining state and props and makes a holistic assumption that if the next state/prop references haven't changed then the values haven't changed and thus returns the last computed rendered DOM. This is the important detail of updating react state... each update needs to reference a new object.

In your case you are merely saving the reference to the current array in state, mutating it, and resaving it. Since the reference is stable and doesn't change, react doesn't re-render.

const otc = () => {
  let k = newarray; // <-- saved array reference!!
  setnewarray(k.sort((a, b) => (a.time > b.time) ? -1 : 1 ));
}

The correct react way is to copy the current array values into a new array so it will have a new object reference.

const otc = () => {
  const newSortedArray = [...newArray].sort(
    (a, b) => (a.time > b.time) ? -1 : 1
  ); // spread old array values into new array, then sort
  setNewArray(newSortedArray);
}

这篇关于React/react hooks:子组件在状态改变后不重新渲染?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
前端开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆