【问题标题】:In React, how to bind an input's value when rendering a list of inputs?在 React 中,如何在渲染输入列表时绑定输入的值?
【发布时间】:2018-04-27 13:32:27
【问题描述】:

我正在渲染一个输入列表,我想将每个输入的值绑定到链接的 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/

有什么想法吗?

【问题讨论】:

  • 您需要将输入中的文本保存在状态中(使用 setState),而不是在 tweets 数组中。然后你可以用类似 {this.state.tweetsText[tweet.id]}

标签: javascript reactjs ecmascript-6 setstate array.prototype.map


【解决方案1】:

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

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/

【讨论】:

  • 太好了,正是我想要的。你能解释一下index =&gt; e =&gt;吗?如果onChange 中没有引用事件对象e,怎么会传递给setTweets
【解决方案2】:

您可以使用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/

【讨论】:

    【解决方案3】:

    你真的应该在这里使用一个状态,并让你的 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) 替换旧的项目对象,用新的(arr) 替换旧的tweets 数组。


    这是完整的示例:

    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>

    【讨论】:

      【解决方案4】:

      您需要将输入中的文本保存在状态中(使用 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>
          );
        }
      }
      

      【讨论】:

        【解决方案5】:

        链接信息位于 tweets 数组的 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>
            );
          }
        

        【讨论】:

        • 感谢您提供帮助,但这不是我想要实现的目标。 text 属性最初是未设置的,因为它将由用户在输入中手动输入:onChange={e => tweet.text = e.target.value}
        猜你喜欢
        • 2018-11-26
        • 2016-11-23
        • 1970-01-01
        • 2019-10-09
        • 1970-01-01
        • 1970-01-01
        • 2020-05-05
        • 2022-08-07
        • 1970-01-01
        相关资源
        最近更新 更多