在 React 中,如何在呈现输入列表时绑定输入的值?

In React, how to bind an input's value when rendering a list of inputs?

我正在呈现输入列表,我想将每个输入的值绑定到 link 的 href。我目前的尝试呈现 https://twitter.com/intent/tweet?text=undefined:

class App extends React.Component {
  tweets = [
    { id: 1, link: 'example.com' },
    { id: 2, link: 'example2.com' }
  ];

  render() {
    return (
      <div>
        {this.tweets.map(tweet => 
          <div key={tweet.id}>
            <input type="text" placeholder="text" onChange={e => tweet.text = e.target.value} />
            <a href={`https://twitter.com/intent/tweet?text=${tweet.text}`}>Tweet</a>
          </div>
        )}
      </div>
    );
  }
}

这可能需要涉及 setState 但我不知道在渲染列表时如何实现。我试图对此进行一些研究,但没有发现任何有用的东西。

JSFiddle:https://jsfiddle.net/nunoarruda/u5c21wj9/3/

有什么想法吗?

链接信息位于推文数组的 link 属性 中。 属性 text 未定义。 所以,你的渲染函数应该是这样的

  render() {
    return (
      <div>
        {this.tweets.map(tweet => 
          <div key={tweet.id}>
            <input type="text" placeholder="text" onChange={e => tweet.text= e.target.value} />
            <a href={`https://twitter.com/intent/tweet?text=${tweet.link}`}>Tweet</a>
          </div>
        )}
      </div>
    );
  }

您可以使用 state 获得所需的结果。

return (
  <div>
     {tweets.map(({ id, link }) => 
       <div key={id}>
         <input type="text" placeholder="text" onChange={({ target }) => this.setState({ [id]: target.value })} />
         <a href={`https://twitter.com/intent/tweet?text=${this.state[id] || link}`}>Tweet</a>
       </div>
     )}
   </div>
);

注意:我会tweets移到组件之外并实现一些 ES6 功能。

已更新 Jsfiddle:https://jsfiddle.net/u5c21wj9/7/

你真的应该在这里使用一个状态,让你的 tweets 变量成为它的一部分。为此,添加一个构造函数:

constructor() {
  super();
  this.state = {
    tweets: [
      { id: 1, link: 'example.com' },
      { id: 2, link: 'example2.com' }
    ]
  };
}

然后您需要在输入其中一个输入时改变每个 link。这里有一些陷阱,所以让我一一解决:

changeTweet = (id, e) => {
  let arr = this.state.tweets.slice();
  let index = arr.findIndex(i => i.id === id);
  let obj = Object.assign({}, arr[index]);
  obj.link = e.target.value;
  arr[index] = obj;
  this.setState({tweets: arr});
}

首先,您需要创建状态变量的副本。这为您提供了一些可以使用的东西,而无需直接改变反模式的状态。这可以通过 slice().

来完成

由于您要发送要修改的对象的 id,我们需要在我们的数组中找到它(以防项目无序)。这是用 findIndex() 完成的。您可能想要处理找不到此类索引的情况(我没有这样做)。

现在我们知道具有给定 id 键的对象在数组中的位置。现在,创建该项目的副本(这是一个对象)。这也是为了防止直接改变状态。使用 Object.assign().

执行此操作

现在将 link 更改为我们输入的输入值。将旧的项目对象替换为新的 (obj) 并将旧的 tweets 数组替换为新的一 (arr).


完整示例如下:

class App extends React.Component {      
  constructor() {
    super();
   this.state = {
     tweets: [
        { id: 1, link: 'example.com' },
        { id: 2, link: 'example2.com' }
      ]
    };
  }
  
  changeTweet = (id, e) => {
    let arr = this.state.tweets.slice();
    let index = arr.findIndex(i => i.id === id);
    let obj = Object.assign({}, arr[index]);
    obj.link = e.target.value;
    arr[index] = obj;
   this.setState({tweets: arr});
  }

  render() {
    return (
      <div>
        {this.state.tweets.map(tweet => 
          <div key={tweet.id}>
            <input type="text" placeholder="text" onChange={(e) => this.changeTweet(tweet.id, e)} />
            <a href={`https://twitter.com/intent/tweet?text=${tweet.link}`}>Tweet</a>
          </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>

您可以将 tweets 变量移动到状态以保持该数组的一致性。

class App extends React.Component {
  constructor(props) {
   super(props)
    this.state = {
     tweets: [
       { id: 1, link: 'example.com' },
        { id: 2, link: 'example2.com' }
      ]
    };
  };
  
  setTweets = index => e => {
   const { tweets } = this.state
    tweets[index].text = e.target.value
    this.setState({ tweets })
  }

  render() {
   const { tweets } = this.state
    return (
      <div>
        {tweets.map((tweet, index) => 
          <div key={tweet.id}>
            <input type="text" placeholder="text" onChange={this.setTweets(index)} />
            <a href={`https://twitter.com/intent/tweet?text=${tweet.text}`}>Tweet</a>
          </div>
        )}
      </div>
    );
  }
}

已更新 Jsfiddle:https://jsfiddle.net/u5c21wj9/6/

您需要将输入的文本保存在状态中(使用 setState),而不是 tweets 数组中。然后你可以渲染它从状态中获取文本。

class App extends React.Component {
  tweets = [
    { id: 1, link: 'example.com' },
    { id: 2, link: 'example2.com' }
  ];

  state = {
    tweetsText :{}
  }

  handleTextChange = (event, tweetId) => {
     const tweetsTextCopy = Object.assign({}, this.state.tweetsText)
    tweetsTextCopy[tweetId] = event.target.value
    this.setState({tweetsText: tweetsTextCopy})
  }

  render() {
    return (
      <div>
        {this.tweets.map(tweet => 
          <div key={tweet.id}>
            <input type="text" placeholder="text" onChange={e => this.handleTextChange(e, tweet.id)} />
            <a href={`https://twitter.com/intent/tweet?text=${this.state.tweetsText[tweet.id]}`}>Tweet</a>
          </div>
        )}
      </div>
    );
  }
}