如何在表单的选择字段onChange中传递对象值(使用React,不使用Redux)

时间:2018-01-08 22:51:37

标签: javascript reactjs react-bootstrap

我目前正在研究一个简单形式的反应组件(没有redux,只需使用react-bootstrap进行样式化)

我以下列形式从数据库中提取数据:

while($row = $result->fetch_assoc()) {
    $rsv = $row['reserve'];
    $pkey = $row['pkey'];
    if($rsv) { // thats basicly the same as !=0
        $target='../php/plannerR.php'
    } else {
        $target='../php/planner.php'
    }
    echo "<tr><td>".$row['lname']."</td><td>".$row['fname']."</td>";
    echo "<td>".$row['rank']."</td><td>".$row['ment1']."</td>";
    echo "<td><a class='button styleIt' href='".$target."?pkey=".$pkey."&rsv=".$rsv."'>Get Planner</a></td></tr>";
}

并将其放入对象中:

[
  {
    "id":"123",
    "name":"Amy Pond",
    "age":"22",
    "reputation":22000
  },
  {
    "id":"124",
    "name":"Clara Oswald",
    "age":"24",
    "reputation":35000
 }
 ...
]

我使用map来填充基于此数据的下拉列表,并可以从下拉列表中正确设置用户的状态:

let userlist = [];
userlist = addUsers(this.state.users);

使用handleChange()

<FormControl
   id = "user"
   componentClass="select"
   onChange={this.handleChange}
>
   {userlist.map((r , i) =>
     <option
       key={i}
       value={r.name}>
       {r.name}
     </option>
  )}
</FormControl>

我的问题是,我需要用户在handleChange函数中的年龄和声誉来相应地设置其状态。我尝试过handleChange(event) { this.setState({ value: event.target.value, // reputation: ???? // here's where I'm running into issues // age: ??????? // and here }); 而不是r,但我得到了r.name

[object Object]

如果我尝试console.log ("Handle Change Value: " + event.target.value); ,我会回复event.target.value.name

到目前为止,唯一有效的方法是使用JSON.stringify,但我觉得这不是正确的方法。一旦我得到了这个名字,我也想过只搜索一下这些对象,但是如果有很多对象,我觉得这样效率会非常低效?我也不知道该怎么做。

任何人都可以帮我找到一种方法来传递这两个额外的值,以便我可以设置状态吗?地图甚至是创建选项的最佳方式吗?老实说,我觉得这是一件很简单的事情,但是我还是刚刚做出反应,而且我一直在努力解决这个问题太久了!

任何想法/改变/评论/方式,使这更好​​,将非常感谢!我意识到也许使用像redux-form这样的东西可以让这更容易,但是我希望有一个简单的方法来做到这一点,而不是现在。

修改 onChange应该设置为undefined,只是粘贴了我尝试进行故障排除的错误代码。我在构造函数中绑定它:

onChange = {this.handleChange}

3 个答案:

答案 0 :(得分:4)

使用用户ID作为每个option中的值,然后在handleChange中找到userlist中的用户以访问所有用户的属性:

<FormControl
   id = "user"
   componentClass="select"
   onChange={this.handleChange.bind(this)}
>
   {userlist.map((r , i) =>
     <option
       key={i}
       value={r.id}>
       {r.name}
     </option>
  )}
</FormControl>

handleChange(event) {
  const userId = event.target.value;
  const user = userlist.find(u => u.id === userId);
  this.setState({
    value: user
  });
}

此外,传递onChange属性的方式可能会导致问题。在没有看到所有代码的情况下很难分辨,但请确保您传递了对handleChange函数的引用(请参阅我的回答中的上方),而不是在那里调用它(如在您的问题中: onChange={this.handleChange()},除非您的this.handleChange函数返回一个函数。)

答案 1 :(得分:1)

设置事件监听器的方式可能会出现问题,设置onChange={this.handleChange()}会导致监听器立即触发。使用onChange={this.handleChange}正确设置监听器。

<FormControl
   id = "user"
   componentClass="select"
   onChange={this.handleChange}>
   {userlist.map((r , i) =>
     <option
       key={i}
       value={r.name}>
       {r.name}
     </option>
  )}
</FormControl>

有关活动的更多信息,请参阅here

然后,您可以在事件处理程序中使用find()来找到用户:

handleChange(event) {
  let user = users.find(u => u.name === event.user.name);
  this.setState({user: user});
}

答案 2 :(得分:0)

您可以使用选项标签属性和json进行编码/解码,如下所示:

<FormControl
        id="user"
        componentClass="select"
        onChange={this.handleChange.bind(this)}
    >
        {userlist.map((r, i) =>
            <option
                key={i}
                value={r.id}>
                {r.name}
                data={JSON.stringify(r)}
            </option>
        )}
    </FormControl>;

    handleChange(event)
    {
        if (e.target.options && e.target.selectedIndex) {
            const user = e.target.options[e.target.selectedIndex].getAttribute('data');
            this.setState({
                value: user
            });
        }
    }