Javascript-在迭代过程中使用值而不是引用

时间:2018-10-29 12:00:05

标签: javascript scope

使用以下简单方法在ReactJs中创建列表组件:

for (var key in this.props.code_values)
        {
            var current = this.props.code_values[key];
            var current_value = current.value;
            drop_choices.push(<ListItem
                                button
                                key = { current.id }
                                onClick = {(event) => this.makeSomethingWithValue(current_value)}
                              >
                                { current.value }
                              </ListItem>);
        }

问题是current_value是在Click上计算得出的,因此它将始终等于迭代的最后一个current_value。

例如:

code_values = [ { id : 1, value : 1}, { id : 2, value : 2} ]

单击“ 1”将得到“ 2”。

我们不是在“创建” html satic代码,而是创建组件,并且在此迭代过程中不会“创建” OnClick作为属性,而仅在onClick事件之后才“处理”。

3 个答案:

答案 0 :(得分:2)

这是var的范围界定问题,请尝试改用letconst

for (let key in this.props.code_values)
    {
        const current = this.props.code_values[key];
        const current_value = current.value;
        drop_choices.push(<ListItem
                            button
                            key = { current.id }
                            onClick = {(event) => this.makeSomethingWithValue(current_value)}
                          >
                            { current.value }
                          </ListItem>);
    }

答案 1 :(得分:2)

您可以通过其他方法来解决这个问题。

  1. 您可以使用Function.prototype.bind将数据绑定到事件处理程序。像this.makeSomethingWithValue.bind(this, current_value)
  2. 您可以使用Array.prototype.map遍历所拥有的数据,并在如下所示的退货中以这种方式显示它们;

return (
  this.props.code_values.map(current => (
    <ListItem
      button
      key={current.id}
      onClick={(event) => this.makeSomethingWithValue(current.value)}
    >
      { current.value }
    </ListItem>
  ))
);

...

答案 2 :(得分:1)

您应该考虑使用map而不是循环,以获得更好的变量作用域。您可能还考虑将值作为prop而不是函数的参数传递给组件。

这是我如何看待其余代码的模型:

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = { data: props.data };

    // bind `handleClick`
    this.handleClick = this.handleClick.bind(this);
  }
  handleClick(e) {

    // take the value (textContent), coerce to a number and add 10 to it
    console.log(+e.target.textContent + 10);
  }
  render() {
    return (
      <div>
        <ul>

         // `map` over the array in state
         {this.state.data.map(current => {
           return (
             <ListItem
               key = {current.id}

               // pass in value, and the function to be called onClick
               value={current.value}
               handleClick={this.handleClick}
             />
           )
         })}   
        </ul>
      </div>
    )
  }
}

function ListItem({ value, handleClick }) {
  return <li onClick={handleClick}>{value}</li>;
}

const data = [{ id: 1, value: 1}, { id: 2, value: 2}];

ReactDOM.render(
  <App data={data} />,
  document.getElementById('container')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="container"></div>