<div id="root"></div>
body {
  margin: 0;
}
View Compiled
import React from 'https://esm.sh/react@18.2.0'
import ReactDOM from 'https://esm.sh/react-dom@18.2.0'

const npm = [
  'lodash',
  'chalk',
  'request',
  'commander',
  'react',
  'express',
  'debug',
  'async',
  'fs-extra',
  'moment',
  'prop-types',
  'react-dom',
  'bluebird',
  'underscore',
  'vue',
  'axios',
  'tslib',
  'mkdirp',
  'glob',
  'yargs',
  'colors',
  'inquirer',
  'webpack',
  'uuid',
  'classnames',
  'minimist',
  'body-parser',
  'rxjs',
  'babel-runtime',
  'jquery',
  'yeoman-generator',
  'through2',
  'babel-core',
  'core-js',
  'semver',
  'babel-loader',
  'cheerio',
  'rimraf',
  'q',
  'eslint',
  'css-loader',
  'shelljs',
  'dotenv',
  'typescript',
  '@types/node',
  '@angular/core',
  'js-yaml',
  'style-loader',
  'winston',
  '@angular/common',
  'redux',
  'object-assign',
  'zone.js',
  'babel-eslint',
  'gulp',
  'gulp-util',
  'file-loader',
  'ora',
  'node-fetch',
  '@angular/platform-browser',
  '@babel/runtime',
  'handlebars',
  'eslint-plugin-import',
  '@angular/compiler',
  'eslint-plugin-react',
  'aws-sdk',
  'yosay',
  'url-loader',
  '@angular/forms',
  'webpack-dev-server',
  '@angular/platform-browser-dynamic',
  'mocha',
  'html-webpack-plugin',
  'socket.io',
  'ws',
  'babel-preset-es2015',
  'postcss-loader',
];

const useDebounce = (value, delay = 400) => {
  const [debounceValue, setDebounceValue] = React.useState(value);

  React.useEffect(() => {
    const timer = setTimeout(() => {
      setDebounceValue(value);
    }, delay);

    return () => {
      clearTimeout(timer);
    };
  }, [value, delay]);

  return { debounceValue };
};

const App = () => {
  const [searchInput, setSearchInput] = React.useState('');
  const [count, setCount] = React.useState(0);
  const { debounceValue } = useDebounce(searchInput);
  const tags = npm.filter(v =>
    v.toLowerCase().includes(debounceValue.toLowerCase())
  );

  const api = () => setCount(prev => prev + 1);

  React.useEffect(api, [debounceValue]);

  return (
    <div>
      <p style={{ fontSize: '20px' }}>
        <b>npm 패키지 검색</b>
      </p>
      <p>API 호출: <b>{count}회</b></p>
      <input
        type="text"
        value={searchInput}
        onChange={e => setSearchInput(e.target.value)}
        style={{
          paddingLeft: '6px',
          marginBottom: '5px',
          border: '1px solid black',
        }}
      />
      <div
        style={{
          display: 'flex',
          flexWrap: 'wrap',
          gap: '3px',
          width: '100%',
          height: '100%',
        }}
      >
        {tags.map((tag, i) => (
          <p
            key={i}
            style={{
              padding: '1px',
              border: '1px solid black',
              backgroundColor: '#FBD28D',
            }}
          >
            {tag}
          </p>
        ))}
      </div>
    </div>
  );
};

ReactDOM.render(<App />,
document.getElementById("root"))
View Compiled

External CSS

  1. https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.4/css/bulma.min.css

External JavaScript

This Pen doesn't use any external JavaScript resources.