user7522621
user7522621

Reputation:

input values are inline, not separated by line breaks

I'm a reactJS newbie and I'm practising by creating a simple example that the expected result is, each input value (separated by whitespace) inserted in an HTML element (<h1>). What it executed instead is each output value disappears when it's being separated by space. It's much better to copy-paste the code below on your own project to understand exactly what I mean.

import React from 'react';

class Items extends React.Component {
  constructor() {
    super();
    this.state = {
      result: ''
    }

    this.showItems = this.showItems.bind(this);
  }

  render() {
    let results = this.state.result,
        resultItem = [];

    for(var i=0; i<results.length; i++) {
      resultItem = results[i];
    }

    return(
      <div>

        /* Example, the user typed "Item1 Item2 Item3" */
        <input type='text' placeholder='Enter items' onChange={this.showItems} />

        <div className='result'>
          <h1>{resultItem}</h1>
          /*
            Here, the displayed result should be:

            <h1>Item1</h1>
            <h1>Item2</h1>
            <h1>Item3</h1>
          */
        </div>

      </div>
    );
  }

  itemsResult(result) {
    this.setState({result});
  }

  showItems(e) {
    const items = e.target.value.split(' ');
    this.itemsResult(items);
  }
}

export default Items;

How can I fix this?

Upvotes: 1

Views: 60

Answers (5)

Shubham Khatri
Shubham Khatri

Reputation: 281676

You need to map over the array that you create after splitting by space

class Items extends React.Component {
  constructor() {
    super();
    this.state = {
      result: []
    }

    this.showItems = this.showItems.bind(this);
  }

  render() {
   
    return(
      <div>

        
        <input type='text' placeholder='Enter items' onChange={this.showItems} />

        <div className='result'>
          {this.state.result.length > 0 && this.state.result.map(function(item , index){
           return <h1 key={index}>{item}</h1>
          })}
          
        </div>

      </div>
    );
  }

  itemsResult (result) {
  console.log(result)
    this.setState({result});
  }

  showItems(e) {
    const items = e.target.value.split(' ');
    this.itemsResult(items);
  }
}

ReactDOM.render(<Items/>, 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>

Upvotes: 1

Ved
Ved

Reputation: 12093

Your Mistake is , in loop you are assigning last value to resultItem. You need to push data to resultItem using array push() method. Everything else seems good. Better way is to use .map() instead of for loop

resultItem = [];

for(var i=0; i<results.length; i++) {
   resultItem = results[i];//You are assigning resultItem only last value
}

Should Be:

resultItem = [];

for(var i=0; i<results.length; i++) {

 resultItem.push(<h1 key={i}>{results[i]}</h1>);
}

USING .map() Method:

   <div className='result'>
      {this.state.result.length>0 && this.state.result.map(function(item , index){
       return <h1 key={index}>{item}</h1>
      })}

Upvotes: 1

Ian Emnace
Ian Emnace

Reputation: 1098

Two things in your code are problematic.

  1. You're reassigning resultItem every time in the for loop. See:

    resultItem = results[i];

After the for loop ends, resultItem will only contain the last element of results.

  1. You're rendering an array of strings directly within a <h1> element. See:

    <h1>{resultItem}</h1>

React can understand what to do with arrays, but it'll only render the items one after the other. You should include the h1 tags within the array themselves. Idiomatic way to do it is to use Array#map:

// ...
{
  resultItem.map(str => <h1>str</h1>)
}
// ...

By the way, your resultItem variable looks extraneous. Just render results instead, you're basically just making a copy of it for resultItem anyway.

Upvotes: 0

Mayank Shukla
Mayank Shukla

Reputation: 104379

Use this:

class Items extends React.Component {
      constructor() {
        super();
        this.state = {
          result: ''
        }
    
        this.showItems = this.showItems.bind(this);
      }

      showItems(e) {
         const items = e.target.value;
         this.setState({result: items});
      }
    
      renderValues(){
         let data = this.state.result;
         return data.split(' ').map((el, i) => <h1 key={i}>{el}</h1>)
      }
    
      render() {
    
        return(
          <div>
            <input type='text' placeholder='Enter items' onChange={this.showItems} />
    
            <div className='result'>

              {this.renderValues()}

            </div>
    
          </div>
        );
      }
    }

ReactDOM.render(<Items/>, 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'/>

Upvotes: 0

Richa Garg
Richa Garg

Reputation: 1926

Problem is with your for loop. It should be:

for(var i=0; i<results.length; i++) {
      resultItem.push(results[i]);
    }

or if you want to create a separate tag for each item, you can do:

const list = resultItems.map((item) => <p>{item}</p>)

Note:

May be you can create a listitems. You should not have multiple h1. Also, comments does not work in the render section. So you should remove that.

Upvotes: 0

Related Questions