Skip to content

Commit

Permalink
feat: added useClassNames
Browse files Browse the repository at this point in the history
  • Loading branch information
cecilia-sanare committed Jan 9, 2024
1 parent 0c47a70 commit a3adcbb
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 21 deletions.
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
"peerDependencies": {
"react": "*"
},
"dependencies": {
"classnames": "^2.5.1"
},
"devDependencies": {
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^14.0.0",
Expand Down Expand Up @@ -52,8 +55,5 @@
"type": "git",
"url": "git+https://github.com/rain-cafe/react-utils.git"
},
"license": "MIT",
"dependencies": {
"classnames": "^2.5.1"
}
"license": "MIT"
}
54 changes: 37 additions & 17 deletions src/hooks/__tests__/use-cached-state.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,19 @@
import { render } from '@testing-library/react';
import { useCachedState, useReadOnlyCachedState } from '../use-cached-state';
import { useCachedState, useClassNames, useReadOnlyCachedState } from '../use-cached-state';
import Chance from 'chance';

const chance = new Chance();

type ExampleComponentProps = {
value: string;
};

describe('Cached State Hooks', () => {
describe('hook(useCachedState)', () => {
function ExampleComponent({
value
}: ExampleComponentProps) {
type ExampleComponentProps = {
value: string;
};

function ExampleComponent({ value }: ExampleComponentProps) {
const [internalValue] = useCachedState(() => value, [value]);

return (
<div>{internalValue}</div>
);
return <div>{internalValue}</div>;
}

it('should cache the value', () => {
Expand All @@ -30,14 +26,14 @@ describe('Cached State Hooks', () => {
});

describe('hook(useReadOnlyCachedState)', () => {
function ExampleComponent({
value
}: ExampleComponentProps) {
type ExampleComponentProps = {
value: string;
};

function ExampleComponent({ value }: ExampleComponentProps) {
const internalValue = useReadOnlyCachedState(() => value, [value]);

return (
<div>{internalValue}</div>
);
return <div>{internalValue}</div>;
}

it('should cache the value', () => {
Expand All @@ -48,4 +44,28 @@ describe('Cached State Hooks', () => {
expect(component.getByText(expectedValue)).toBeTruthy();
});
});

describe('hook(useClassNames)', () => {
type ExampleComponentProps = {
sticky?: boolean;
};

function ExampleComponent({ sticky }: ExampleComponentProps) {
const classes = useClassNames(['my-class', sticky && 'sticky']);

return <div data-testid="example" className={classes} />;
}

it('should support base classes', () => {
const component = render(<ExampleComponent />);

expect(component.getByTestId('example').className).toEqual('my-class');
});

it('should support conditional classes', () => {
const component = render(<ExampleComponent sticky />);

expect(component.getByTestId('example').className).toEqual('my-class sticky');
});
});
});
7 changes: 7 additions & 0 deletions src/hooks/use-cached-state.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import classNames, { ArgumentArray } from 'classnames';
import { DependencyList, Dispatch, SetStateAction, useEffect, useState } from 'react';

export function useCachedState<T>(
Expand All @@ -16,3 +17,9 @@ export function useReadOnlyCachedState<T>(supplier: () => T, deps: DependencyLis

return value;
}

export function useClassNames(deps: ArgumentArray): string {
return useReadOnlyCachedState(() => {
return classNames(deps);
}, deps);
}

0 comments on commit a3adcbb

Please sign in to comment.