【问题标题】:Handle Input with Same State Value处理具有相同状态值的输入
【发布时间】:2018-11-15 07:21:01
【问题描述】:

我正在构建一个购物车应用程序,但遇到了一个问题,即我的所有输入都具有相同的状态值。一切正常,但是当我在一个输入框中输入时,所有其他输入都是一样的。

我尝试在输入中添加一个名称字段并将我的初始状态设置为未定义,这工作正常,但数字不通过。

当输入具有相同的状态值时,我们如何处理不同的输入?或者这是不可能/愚蠢的吗?

class App extends Component {
  state = {
    items: {
      1: {
        id: 1, name: 'Yeezys', price: 300, remaining: 5
      },  

      2: {
        id: 2, name: 'Github Sweater', price: 50, remaining: 5
      },

      3: {
        id: 3, name: 'Protein Powder', price: 30, remaining: 5
      }
    },
    itemQuantity: 0
  },

  render() {
    return (
      <div>
        <h1>Shopping Area</h1>
        {Object.values(items).map(item => (
          <div key={item.id}>
            <h2>{item.name}</h2>
            <h2>$ {item.price}</h2>
            {item.remaining === 0 ? (
              <p style={{ 'color': 'red' }}>Sold Out</p>
            ) : (
              <div>
                <p>Remaining: {item.remaining}</p>
                <input 
                  type="number"
                  value={ itemQuantity }
                  onChange={e => this.setState({ itemQuantity: e.target.value})}
                  placeholder="quantity"
                  min={1}
                  max={5}
                />
                <button onClick={() => this.addItem(item)}>Add To Cart</button>
              </div>
            )}
          </div>
        ))}
      </div>
    )
  }
}

【问题讨论】:

  • 您在多个项目中使用相同的状态并想知道......他们有相同的状态?
  • @JonasW 我知道它们具有相同的价值,但我想知道是否有办法使它们独一无二。如果我有 10000 个项目,我不会为每个项目提供 10000 个输入
  • @ionizer 不错的解决方案。我会试试的。 :)
  • 或者,您可以在这些项目中插入一个新属性来跟踪数量并动态设置它,就像我对答案所做的那样。

标签: javascript reactjs


【解决方案1】:

如果您对所有输入使用相同的状态键,则所有输入都从一个位置获取值并更新到一个位置。为避免这种情况,您必须使用单独的状态。我想您正在尝试显示项目列表的输入。

要实现这一点,您可以为列表项创建一个组件并在列表项组件中保持状态。由于每个组件都有自己的状态,因此状态值不会冲突。

这是一个例子

class CardItem extends Component {
    state = {
        number: 0
    }

    render() {
        render (
            <input type="text" value={this.state.number} onChange={e => this.setState({ number: e.target.value })} />
        )
    }
}

class Main extends Component {
    render () {
        const list = [0,1,2,3,4]

        return (
            list.map(item => <CardItem data={item} />)
        )
    }
}

【讨论】:

  • 应该想到这一点。谢谢。
【解决方案2】:

这是一个问题被松散解释的解决方案,但它确实可以工作,而无需创建另一个组件。如您所知,您需要分离购物车中每个项目的状态。我通过动态初始化和设置每个项目的数量状态来做到这一点。你可以通过这个例子看到状态变化:

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

  componentDidMount() {
    let itemIDs = ['1', '2', '3', 'XX']; //use your own list of items
    itemIDs.forEach(id => {
      this.setState({quantities: Object.assign(this.state.quantities, {[id]: 0})});
    })
  }

  render() {
    let list = Object.keys(this.state.quantities).map(id => {
      return (
        <div>
          <label for={id}>Item {id}</label>
          <input
            id={id}
            key={id}
            type="number"
            value={this.state.quantities[id]}
            onChange={e => {
              this.setState({quantities: Object.assign(this.state.quantities, {[id]: e.target.value})})
            }}
          />
        </div>
      );
    })
    return (
      <div>
        {list}
        <div>STATE: {JSON.stringify(this.state)}</div>
      </div>
    );
  }
}

ReactDOM.render(<App/>, document.getElementById('root'));
<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='root'></div>

您可以根据自己的喜好修改状态结构。

【讨论】:

  • 在我继续前进时最终得到了您的答案,并将数量属性应用于我的每个项目并设置为目标值。谢谢! :)
【解决方案3】:

这是我通常处理这种情况的方式。你说你得到了一系列项目?每个项目对象都应该包含一个存储值的键(在我的示例中为count)。您可以使用通用 onChange 处理程序来更新数组中的单个项目。所以现在,您的状态是管理项目列表而不是每个单独的输入值。这使您的组件更加灵活,并且无需更改代码即可处理任意数量的项目:

const itemData = [
{ id: 0, count: 0, label: 'Number 1' },
{ id: 1, count: 0, label: 'Number 2' },
{ id: 2, count: 0, label: 'Number 3' },
{ id: 3, count: 0, label: 'Number 4' }
];

class App extends React.Component {

  state = {
    items: itemData
  }
  
  handleCountChange = (itemId, e) => {
    // Get value from input
    const count = e.target.value;
    this.setState( prevState => ({
      items: prevState.items.map( item => {
        // Find matching item by id
        if(item.id === itemId) {
          // Update item count based on input value
          item.count = count;
        }
        return item;
      })
    }))
  };
  
  renderItems = () => {
    // Map through all items and render inputs
    return this.state.items.map( item => (
       <label key={item.label}>
          {item.label}:
          <input
            type="number"
            value={item.count}
            onChange={this.handleCountChange.bind(this, item.id)}
          />
        </label>
    ));
  };

  render() {
    return (
      <div>
       {this.renderItems()}
      </div>
    )
  }
}

ReactDOM.render(<App />, document.getElementById('root'));
label {
  display: block;
}
<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="root"></div>

【讨论】:

    【解决方案4】:

    您不能对两个输入使用相同的状态。尝试为每个状态使用不同的状态:

    class App extends Component {
    
    
    state = {
        number: ""
      }
    
      render() {
        return (
          <div>
            <input
              type="number"
              value={this.state.number}
              onChange={e => this.setState({ number: e.target.value })}
            />
            <input
              type="number"
              value={this.state.number2}
              onChange={e => this.setState({ number2: e.target.value })}
            />
          </div>
        )
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-07-31
      • 2021-08-13
      • 2016-03-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-01
      • 2019-02-23
      相关资源
      最近更新 更多