在React功能组件中更改状态后组件不会重新呈现

时间:2020-04-15 15:42:00

标签: javascript reactjs react-hooks

我正在尝试使用另一个文件中的数组来创建带有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>
       ))}
    );
};

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

4 个答案:

答案 0 :(得分:0)

直接修改状态是一种不好的做法。相反,如果您有arr2.length > 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()方法将创建一个新数组,其中包含所有通过提供的功能实现的测试的元素。

我希望这会有所帮助!

答案 1 :(得分:0)

尝试一下

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>
       ))}
    );

答案 2 :(得分:0)

arr2只是对您的状态的引用,您无法对其进行修改,可以执行以下操作:

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

答案 3 :(得分:0)

尝试一下:

var app = angular.module("myApp", ["ngRoute","ngMaterial","ui.bootstrap"]);

app.config(function($routeProvider,$locationProvider) {
  $locationProvider.html5Mode(true);
  $routeProvider
  .when('/task',{
    templateUrl : 'task.html',
    controller  : 'taskController'
  });
});

app.service('serviceStorage', function() {
  this.myFunc1 = function () {
      return JSON.parse(localStorage.getItem("pendingArray"));
  }
});

app.controller('taskController',function($scope,$mdDialog,$rootScope,serviceStorage){
  console.log("task controller loaded",serviceStorage.myFunc1());


  if(serviceStorage.myFunc1() == null){
    $rootScope.pending = [];
  }
  else{
    $rootScope.pending = serviceStorage.myFunc1();
  }
  console.log("rs ",$rootScope.pending.length);
  $rootScope.inProcess = [];
  $scope.completed = [];

  $scope.openTaskDialog = function(index,status){
    console.log("clicked task dialog");

    $mdDialog.show({
      controller: DialogController,
      templateUrl:'addTasks.html'
    })

    function DialogController($scope, $rootScope, $mdDialog) {
      console.log("dialog controller opened");

      $scope.formSubmit = function(formObj){
        if(status == 'pending'){
          $rootScope.pending[index].taskTitle = $scope.formObj.taskTitle;
          $rootScope.pending[index].description = $scope.formObj.description;
          $rootScope.pending[index].process = $scope.formObj.process;
          localStorage.setItem("pendingArray",JSON.stringify($rootScope.pending));
        }
        else if(status == 'inProcess'){
          $rootScope.inProcess[index].taskTitle = $scope.formObj.taskTitle;
          $rootScope.inProcess[index].description = $scope.formObj.description;
          $rootScope.inProcess[index].process = $scope.formObj.process;
        }
        else{
          console.log("2" ,$scope.formObj.taskTitle);
          console.log("form data",formObj);
          $rootScope.pending.push(formObj);
          console.log($rootScope.pending);
          localStorage.setItem("pendingArray",JSON.stringify($rootScope.pending));
        }

        $mdDialog.hide();
      }

      $scope.cancel = function(){
        console.log("cancel");
        $mdDialog.hide();
      }

    }

  }

  $scope.deleteTask = function(index,status){
    console.log("status ",status);
    if(status == 'pending'){
      $rootScope.pending.splice(index,1);
      console.log("$rootScope",$rootScope.pending);
      console.log("index ",$rootScope.pending[index]);
      localStorage.setItem("pendingArray",JSON.stringify($rootScope.pending));
    }
    else if(status == 'inProcess'){
      $scope.inProcess.splice(index,1);
      console.log("inProcess ",$scope.inProcess);
    }

  }

});