React 功能组件中状态更改后组件未重新渲染

Posted

技术标签:

【中文标题】React 功能组件中状态更改后组件未重新渲染【英文标题】:Component not re rendering after state changing in React functional component 【发布时间】:2020-07-28 15:56:15 【问题描述】:

我正在尝试使用来自另一个文件的数组创建一个带有 React useState 的推荐选框类型组件,但我的组件在更改数组后不会重新呈现。它应该每 2 秒更改一次。

根据我的控制台日志,我的状态正在正确更改。但是组件只是没有重新渲染。

我的外部数据如下所示:

export const testimonials = [
    
        img     : "",
        info    : "",
        company : "",
        link    : ""
    ,
    
        img     : "",
        info    : "",
        company : "",
        link    : ""
    ,...

不确定它是否因为概括它看起来像这样而没有重新渲染?这只是一个猜测。 [对象][对象][对象]

const Testimonials = ( classes ) => 
    const [ arr, setArr ] = useState(testimonials);

    const IncrementTestimonials = (arr2) => 
        let el = arr2.shift();
        arr2.push(el);
        setArr(arr2);
        console.log('changed');
    ;

    useEffect(
        () => 
            setInterval(() => 
                console.log('changing');
                IncrementTestimonials(arr);
            , 2000);
        ,
        [ arr ]
    );

    return (
      arr.map((e) => (
            <div className=classes.Card>
               <p>"e.info"</p>
             </div>
       ))
    );
;

任何帮助将不胜感激, 谢谢。

【问题讨论】:

【参考方案1】:

arr2 只是对你的状态的引用,你不能修改它,你可以这样做:

const IncrementTestimonials = () => 
    const arr2 = [...arr];
    let el = arr2.shift();
    arr2.push(el);
    setArr(arr2);
    console.log('changed');
;

【讨论】:

【参考方案2】:

直接修改状态是不好的做法。相反,如果你有arr2.length &gt; 0,你可以获得第一个元素。然后使用 .filter() 您可以按索引删除第一个元素。然后使用setState() 的回调选项。

尝试如下:

const IncrementTestimonials = (arr2) => 
    if (arr2.length > 0) 
       const firstElem = arr2[0];

       const filteredArray = arr2.filter((e, i) => i !== 0);

       setArr(prevArr => filteredArray.concat(firstElem));
    
;

使用.filter(),您将拥有一个新数组,请参阅文档:

filter() 方法创建一个新数组,其中包含所有通过所提供函数实现的测试的元素。

我希望这会有所帮助!

【讨论】:

【参考方案3】:

试试这个

const IncrementTestimonials = () => 
        let arr2 = [...arr]
        let el = arr2.shift();
        arr2.push(el);
        setArr(arr2);
        console.log('changed');
    ;

 useEffect(
        () => 
            const timer = setTimeout(() =>  // use timeout as after every 2 seconds , your effect will run
                console.log('changing');
                IncrementTestimonials();
            , 2000);
            return ()=>
               clearTimeout(timer); 
            
        ,
        [ arr ]
    );

    return (
      arr.map((e) => (
            <div className=classes.Card>
               <p>`$e.info`</p> // use string interpolation i.e backticks
             </div>
       ))
    );

【讨论】:

【参考方案4】:

试试这个:

 const IncrementTestimonials = (arr2) => 
      let el = arr2.shift();
      arr2.push(el);
      setArr(JSON.parse(JSON.stringify(arr2)));
      console.log('changed ' + arr[0].company);
  ;

【讨论】:

我最初的推荐数组是一个对象数组,这有关系吗? 不是真的,只是想知道您是在尝试动态获取推荐还是已经预先填充。 是的,它们都预先填充在另一个文件中。 刚刚更新了我的评论,这个改动会强制数组更新数组。突变是数组的问题【参考方案5】:

使用扩展... 运算符

setArr([...arr2])

参考:https://developer.mozilla.org/en-US/docs/Web/javascript/Reference/Operators/Spread_syntax

【讨论】:

您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center。

以上是关于React 功能组件中状态更改后组件未重新渲染的主要内容,如果未能解决你的问题,请参考以下文章

为啥组件在状态更改后不重新渲染。在 react-native 函数组件中

React 功能组件在状态更改后不更新

React Native:状态更改后无法重新渲染图像

组件不会重新渲染,但 redux 状态已通过反应钩子更改

React hooks 功能组件防止在状态更新时重新渲染

如何通过使用功能组件更新 React 中的状态来重新渲染页面。?