jsartisan / frontend-challenges

FrontendChallenges is a collection of frontend interview questions and answers. It is designed to help you prepare for frontend interviews. It's free and open source.
https://frontend-challenges.com
21 stars 4 forks source link

classNames #10

Closed jsartisan closed 4 months ago

jsartisan commented 4 months ago

Info

difficulty: medium
title: classNames
template: javascript
tags: javascript

Question

In React, managing classNames dynamically can become cumbersome. While using the className prop allows adding classes to elements, it becomes verbose when class names are dynamically generated. To streamline this process, developers often turn to libraries like classnames.

Consider the following scenario:

// Original usage
<p className={`classname1  ${condition ? 'classname2' : ''}`}>
  Frontend Challenges
</p>

// With classNames library
import classNames from 'classnames';

// Usage of classNames
classNames('class1', 'class2', class3); 
// 'class1 class2 class3'

classNames({ class1: [], class2: true, class3: 3 }); 
// 'class1 class2 class3'

classNames('class1', { class2: true, class3: false }); 
// 'class1 class2'

Your task is to implement your own version of classNames() function, which accepts arbitrary arguments, filters out falsy values, and generates the final className string. The function should handle various types of inputs, including strings, numbers, objects, and arrays. Ensure that object keys are kept if the key is a string and the corresponding value is truthy. Arrays should be flattened to accommodate nested structures.

Template

index.js

export const classNames = (...args) => {
  // your answer here
};

index.test.js

import { classNames } from './';

describe('classNames utility function', () => {
  it('should concatenate strings and numbers', () => {
    expect(classNames('classname1', 'classname2', 100)).toBe('classname1 classname2 100');
  });

  it('should filter out falsy values', () => {
    expect(classNames(null, undefined, Symbol(), 1n, true, false)).toBe('');
  });

  it('should keep object keys if the key is string and the value is truthy', () => {
    const obj = new Map();
    obj.cool = '!';

    expect(classNames({ class1: [], class2: true, class3: 3 }, obj)).toBe('class1 class2 class3 cool');
  });

  it('should flatten arrays and concatenate classNames', () => {
    const obj = new Map();
    obj.cool = '!';

    expect(classNames(['class1', [{ class2: true }, ['class3', [obj]]]])).toBe('class1 class2 class3 cool');
  });

  it('should handle string and number inputs directly', () => {
    expect(classNames('class1', 100)).toBe('class1 100');
  });

  it('should return an empty string if no arguments are provided', () => {
    expect(classNames()).toBe('');
  });
});
github-actions[bot] commented 4 months ago

12 - Pull Request updated.