使用setState更改对象数组中的多个值-ReactJS

时间:2018-10-16 21:04:11

标签: javascript arrays reactjs state

我是React的新手,并且想编写一个有趣的项目来掌握这种语言。我想编写一个吹泡泡的应用程序,就像这样,我写了以下JSFiddle

我正在渲染以以下方式存储的气泡对象数组:

history =
 [ { //first element is empty placeholder
    diameter: 0,
    x: 0,
    y: 0
  }, 
  { 
    diameter: 40,
    x: 158,
    y: 122
  },
  { 
    diameter: 86,
    x: 274,
    y: 214
  },
  { 
    diameter: 26,
    x: 158,
    y: 244
  },
]

此精确数组将产生以下结果:

enter image description here

现在,在模拟了这一点之后,我有了疯狂的想法来增加一些重力并弹跳。我希望气泡像这样JSFiddle那样反弹:

但是,使气泡运行的唯一方法是直接将信息存储在状态中,如下面的代码所示。 (vy是球的垂直速度。)

class Box extends React.Component {
constructor(props) {
    super(props);
    this.state = {
        diameter: 0,
        x: 0,
        y: 0,
        vy: 0,
        clicked: false,
    };
}

我使用以下代码更新box的状态,以模拟气泡的弹跳:

fall(i){
    this.setState({
        y: this.state.y + i,
        vy: this.state.vy + .01,
    });
}

fallWrap(){
    this.fall(this.state.vy);
    this.u = setTimeout(this.fallWrap.bind(this), 1);



    if(this.state.y >= 400 - (this.state.diameter/2)){
        this.setState({
            y: 400 - (this.state.diameter/2),
            vy: -.9 * this.state.vy,
        }, function(){
            if(Math.abs(this.state.vy) < .2){
                clearTimeout(this.u);
            }
        });
    }

}

我想做的是像第一个JSfiddle一样存储多个气泡数组,并像第二个JS fiddle一样在框中弹出所有气泡。这意味着同时更新历史记录数组中多个对象的值vy。我希望我已经充分描述了我的需求。我的中心问题是如何使用setstate更新数组中存储的每个对象内的单个值(vy)?例如,如果我有

history =
 [ { 
    diameter: 0,
    x: 0,
    y: 0,
    vy: 0
  }, 
  { 
    diameter: 40,
    x: 158,
    y: 122,
    vy: .5 //update this
  },
  { 
    diameter: 86,
    x: 274,
    y: 214,
    vy: .4 //update this
  },
  { 
    diameter: 26,
    x: 158,
    y: 244
    vy: .23 //update this
  },
]

然后我如何以更新每个vy的方式实现setState?我知道在React中,状态数组应该是不可变的,所以我想知道是否存在建立此方法的方法。地图功能似乎很有希望,但是我不知道如何在这里应用它。

编辑:谢谢大家,我最终使用Haken解决方案解决了我的问题。这是指向JSFiddle

的链接

3 个答案:

答案 0 :(得分:2)

您可以将更新程序函数传递给setState。这是一个可能如何工作的示例。

从updater函数返回的对象将被合并到以前的状态。

const updateBubble = ({y, vy, ...props}) => ({y: y + vy, vy: vy + 0.1, ...props})

this.setState(state => ({bubbles: state.bubbles.map(updateBubble)}))

更改updateBubble函数以添加弹跳等。

答案 1 :(得分:1)

您确实可以使用map进行此操作。这就是我要做的。

一个班轮

 var site = angular.module('site', ["ngRoute"]);
 var initInjector = angular.injector(['ng']);
 var $http = initInjector.get('$http');
 site.config(function($routeProvider,$locationProvider){
    $http.get("requests/views.php")
    .then(function (response) {
        var views = response.data.views;
        $.each(views, function(i){
            console.log(views[i].link)
                $routeProvider.when('/' + views[i].link, {
                templateUrl: views[i].template
                // controller: 'pagesController'
            })
        })

    })

    $routeProvider.when('/', {
        templateUrl: "template/home.php"
    })
})

更明确

<?php
header("Access-Control-Allow-Origin: *");
header("Content-Type: application/json; charset=UTF-8");

$conn = new mysqli("localhost", "root", "", "database");

$result = $conn->query("SELECT * FROM pages");

$views = "";
while($view = $result->fetch_array(MYSQLI_ASSOC)) {
    if($views != ""){$views .= ",";}
    $views .= '{"id":"' .$view["id"]. '",';
    $views .= '"title":"' .$view["title"]. '",';
    $views .= '"type":"' .$view["type"]. '",';
    $views .= '"link":"' .$view["link"]. '",';
    $views .= '"template":"' .$view["template"]. '",';
    $views .= '"params":"' .$view["params"]. '"}';
}
$views = '{"views":['.$views.']}';
$conn->close();

echo($views);

答案 2 :(得分:0)

我建议您应该改变方法。您应该只按显示的第一个状态管理状态,然后在另一个组件中管理您当前拥有的组件的次数。

您可以使用类似这样的内容:

import React from 'react'
import Box from './box'

export default class Boxes extends React.Component {
    constructor(props) {
        super(props);
        this.state = { 
            started:[false,false,false,false] /*these flags will be changed on your "onClick" event*/
        } 
    }
    render() {
        const {started} = this.state
        return(
            <div>
              {started[0] && <Box />}
              {started[1] && <Box />}
              {started[2] && <Box />}
              {started[3] && <Box />}
            </div>
        )
    }
}