简体   繁体   English

将项目添加/删除到数组中

[英]React adding/removing items to an array

so I am learning react js and i have stumbled upon a problem which i can't seem to solve.所以我正在学习 react js,我偶然发现了一个我似乎无法解决的问题。 So i have one input that sets the number of break points, and as that number get bigger, more inputs are rendered, and those inputs are for giving a value for each 'breakpoint'.所以我有一个输入来设置断点的数量,随着这个数字变大,更多的输入被渲染,这些输入用于为每个“断点”提供一个值。 Now this is what i can't seem to figure out, if I type in for example '20' and '30' they are added to the array, no problem, however if I want to change the value of the first one(20) to a lower value, let's say 10 I can't figure out how to remove the existing 20 and replace it with a new one(10)... Here's the codepen: https://codepen.io/anon/pen/MVZMRq现在这是我似乎无法弄清楚的,如果我输入例如“20”和“30”,它们将被添加到数组中,没问题,但是如果我想更改第一个的值(20 ) 到一个较低的值,假设 10 我不知道如何删除现有的 20 并将其替换为一个新的(10)......这是代码笔: https ://codepen.io/anon/pen/ MVZMRq

so far i have this:到目前为止,我有这个:

class App extends React.Component {
constructor() {
    super();

    this.state = {
        breakPointsCount: 0,
        range: []
    }
}
addBreakPoints(event) {
    this.setState({
        breakPointsCount: parseInt(event.target.value, 10),
        progress: 0,
        range: []
    });
}

addBreakPointValue(event) {
    const enteredValue = parseInt(event.target.value, 10);
    const range = this.state.range.slice(0);
    const breakpointsCount = this.state.breakPointsCount;
  
    if (range.length < breakpointsCount) {
        range.push(enteredValue);
    }

    this.setState({
        range: range,
        progress: 0,
    });
}

render() {
    const range = this.state.range;
    const breaks = Array.from(Array(this.state.breakPointsCount));

    return (
        <div className="progress">
          [{range.map((item, i) => (
            <div key={item}>
              <span className="break-point-value">{item}</span>
            </div>
          ))}]
        
          <div className="progress-options">
            <label>Change count of break points (up to 10) </label>

            <input type="number"
              min="0"
              max="10"
              name="numberInput"
              className="app-input"
              onChange={this.addBreakPoints.bind(this)}
              />
          </div>
          <div className="progress-options">
            <label>Change a value for each break point </label>

            {breaks.map((item, i) => (
              <input type="number"
                key={`break-${i}`}
                className="app-input"
                onBlur={this.addBreakPointValue.bind(this)}
                />
            ))}

          </div>
        </div>
    )
}
}
React.render(<App />, document.getElementById('app'));

Here is the link to fixed codepen .这是固定codepen的链接。 I have made two changes.我做了两个改变。
First in addBreakPoints method i init the range to array of the size of the input initialized with zeroes (for 5 its gonna be [0,0,0,0,0] )首先在addBreakPoints方法中,我将range初始化为用零初始化的输入大小的数组(对于5它将是[0,0,0,0,0]

    addBreakPoints(event) {
        this.setState({
            breakPointsCount: parseInt(event.target.value, 10),
            progress: 0,
            range: [...Array(parseInt(event.target.value, 10)).map(()=>0)]
        });
    }

next in render() method i bind addBreakPointValue to pass the index of the element to be updated.接下来在render()方法中,我绑定addBreakPointValue以传递要更新的元素的索引。

    {breaks.map((item, i) => (
        <input type="number"
               key={`break-${i}`}
               className="app-input"
               onBlur={this.addBreakPointValue.bind(this,i)}
          />
     ))}

and finally in addBreakPointValue i only update the desired element (map function return same value for all indexes except new value for the index that is passed as parameter to addBreakPointValue )最后在addBreakPointValue我只更新所需的元素(映射函数为所有索引返回相同的值,除了作为参数传递给addBreakPointValue的索引的新值)

    addBreakPointValue(index, event) {
        const enteredValue = parseInt(event.target.value, 10);
        this.setState((prevState) => ({range : prevState.range.map((r,i) => {
          if(i != index) return r
          return enteredValue
        })}))
    }

Hope it is helpful for you.希望对你有帮助。

Edit: Although it now updates values, there is still issues with this code.编辑:虽然它现在更新值,但此代码仍然存在问题。 I will propose a complete solution later.稍后我会提出一个完整的解决方案。

You will need to keep track of which input got changed, so you would want to pass some kind of id to the input.您需要跟踪哪个input了更改,因此您需要将某种id传递给输入。

I recommend using a Component composition instead of binding and passing parameters to the inline handler.我建议使用 Component 组合,而不是将参数绑定和传递给内联处理程序。
You can write a small and simple Input component that all it does is getting a value and id and passing it back up onChange (or onBlur ) in your case.您可以编写一个小而简单的Input组件,它所做的只是获取一个valueid并将其传回onChange (或onBlur )在您的情况下。

Then your change handler could look something similar to this:然后您的更改处理程序可能类似于以下内容:

 addBreakPointValue = (value, id) => {
    this.setState(({range}) => {
      const nextRange = [...range];
      nextRange[id] = value;
      return{
        range: nextRange
      }
    });
  }

I wrote a simple example with your code, note that i changed some stuff, like using arrow functions as handlers (class members) so we can take advantage of their lexical context with this instead of binding the functions to the class .我用你的代码写了一个简单的例子,注意我改变了一些东西,比如使用箭头函数作为处理程序(类成员),这样我们就可以利用它们的词法上下文this而不是将函数bindingclass

 class Input extends React.Component { onBlur = ({ target }) => { const { id, onBlur } = this.props; onBlur(target.value, id); } render() { const { value } = this.props; return ( <input type="number" min="0" max="10" value={value} onBlur={this.onBlur} /> ) } } class App extends React.Component { state = { breakPointsCount: 0, range: [] } addBreakPoints = ({ target }) => { const val = parseInt(target.value, 10); this.setState({ breakPointsCount: val }); } addBreakPointValue = (value, id) => { this.setState(({range}) => { const nextRange = [...range]; nextRange[id] = value; return{ range: nextRange } }); } render() { const { range, breakPointsCount } = this.state; const breaks = Array.from(Array(breakPointsCount)); return ( <div className="progress"> <div className="progress-bar-wrapper"> <div className="progress-bar" style={{ width: `${this.state.progress}%` }} /> [{range.map((item, i) => ( <div key={item}> <span className="break-point-value">{item}</span> </div> ))}] </div> <div className="progress-options"> <label>Change count of break points (up to 10) </label> <input type="number" min="0" max="10" name="numberInput" className="app-input" onChange={this.addBreakPoints.bind(this)} /> </div> <div className="progress-options"> <label>Change a value for each break point </label> {breaks.map((item, i) => ( <Input type="number" key={i} id={i} value={item} className="app-input" onBlur={this.addBreakPointValue} /> ))} </div> </div> ) } } ReactDOM.render(<App />, document.getElementById('app'));
 <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="app"></div>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM