Search code examples
javascriptreactjsnext.jsuser-input

How to create a table with user input?


I'm a newbie in development, so any help is welcome :)

Here's my Problem:

I'm using next.js - this might be important, because f.ex. document.createElement seem only work with useEffect.

I created a text area, where users add words separated with a comma (f.ex. "Nike, Adidas, New Balance"). I want to rewrite the existing code below, so that:

  • table is only visible/appears, when a user adds something in the inputbox
  • each word from the inputbox (f.ex. Nike, Adidas) creates a new row in the table (in table head "Brand").

By now, I was trying to use the .split and .forEach method to create a new Element(table). But I just can't make it work - maybe it's just not the right solution. Any help is welcome!

function Analyzer() {
  
  const [brand, setBrand] = React.useState('');
  const handleChange = (event) => {
    setBrand(event.target.value.split(','))};
  
  return(            
    <div>
      <textarea type="text" 
              placeholder="Example:
              Nike, Adidas, New Balance ..." 
              onChange={handleChange}></textarea>

      <table className={styles.table}>
         <thead>
             <tr>
                <th>No.</th>
                <th>Brand</th>
                <th>Also known as</th>
                <th>Avg. price</th>
             </tr>
          </thead>
          <tbody>
              <tr>
                 <td>1</td>
                 <td>{brand}</td>
                 <td></td>
                 <td><input type= "number"></input>%</td>
              </tr>
          </tbody>
      </table>

     </div>);
}


Solution

  • Try something like the following. What I did was extract the Table component out and put any conditions for its rendering within it. You can even create a separate file for this component and pass any relevant props to it.

    Secondly, I am putting the list of brands into state as brands within the handleChange function. This state variable is then iterated over using .map to render each row in the table.

    function Analyzer() {
      const [brands, setBrands] = React.useState([]);
    
      const handleChange = ({ target }) => {
        const { value } = target;
        setBrands(value.split(','));
      };
    
      const Table = () => {
        if (!brands || brands.length === 0) return null;
    
        return (
          <table className={styles.table}>
            <thead>
              <tr>
                <th>No.</th>
                <th>Brand</th>
                <th>Also known as</th>
                <th>Avg. price</th>
              </tr>
            </thead>
            <tbody>
              {brands.map((brand) => (
                 <tr>
                   <td>1</td>
                   <td>{brand}</td>
                   <td></td>
                   <td><input type= "number"></input>%</td>
                 </tr>
               )}
            </tbody>
          </table>
        );
      };
    
      return(            
        <div>
          <input 
            onChange={handleChange}
            placeholder="Example: Nike, Adidas, New Balance ..."
            type="text"
            value={brands}
          />
          <Table />
       </div>
      );
    };