DEV Community

Cover image for React.js ~Clean Code Practical Use~
Ogasawara Kakeru
Ogasawara Kakeru

Posted on

React.js ~Clean Code Practical Use~

1. The codebase should be created for concentrating on <>JSX Section</>

-The JSX section can often be modified after release.

  • Separate a data-fetching section from the view section.
// NG🤔 You can not comprehend the important point intuitively.
const Area = () => {
  const [user, setUser] = useState();

  useEffect(() => {
    const fetchUser = async (): Promise<void> => {
      const response = await GetUser();
      setUser(response);
    };
    fetchUser();
  }, []);

  return <>{user.name}</>;
};

// Good😎 Separate a data-fetching section from the view section.
const useUser = (): User | undefined => {
  const [user, setUser] = useState<User>();
  useEffect(() => {
    const fetchUser = async (): Promise<void> => {
      const response = await GetUser();
      setUser(response);
    };
    fetchUser();
  }, []);

  return user;
};

// A component for showing data.
const Area = () => {
  const user = useUser();

  return <>{user?.name}</>;
};

Enter fullscreen mode Exit fullscreen mode

2. Don't use too many useState for data-input

// NG🤔 What is going to happen if the `input` element continues to increase...
const UserForm = () => {
  const [name, setName] = useState('');
  const [email, setEmail] = useState('');

  const changeName = (e) => setName(e.target.value);
  const changeEmail = (e) => setEmail(e.target.value);

  return (
    <form onSubmit={onSubmit}>
      <input type='text' value={name} onChange={changeName} />
      <input type='text' value={email} onChange={changeEmail} />
      <input type='submit' value='Submit' />
    </form>
  );
};

// Good😎 Manage submit data in a user object.
const UserForm = () => {
  const [user, setUser] = useState({ name: '', email: '' });

  const changeName = (e) =>
    setUser((state) => ({ ...user, name: e.target.value }));

  const changeEmail = (e) =>
    setUser((state) => ({ ...user, email: e.target.value }));

  return (
    <form onSubmit={onSubmit}>
      <input type='text' value={name} onChange={changeName} />
      <input type='text' value={email} onChange={changeEmail} />
      <input type='submit' value='Submit' />
    </form>
  );
};

// Cool😎: Take advantage of useForm
const UserForm = () => {
   const { register} = useForm();

  return (
    <form onSubmit={onSubmit}>
      <input {...register("name")} />
      <input {...register("email")} />
      <input type='submit' value='Submit' />
    </form>
  );
};

Enter fullscreen mode Exit fullscreen mode

3. Insert a default value to an optional one

type Props = {
  name: string;
  isDisplayNone?: boolean; // An optional props
};

// NG🤔: Defined as isDisplayNone = undefined
const UserCard: FC<Props> = ({ name, isDisplayNone }) => (
  <div style={{ display: isDisplayNone ? 'none' : 'block' }}>{name}</div>
);

// Good😎: Defined as isDisplayNone = false 
const UserCard: FC<Props> = ({ name, isDisplayNone = false }) => (
  <div style={{ display: isDisplayNone ? 'none' : 'block' }}>{name}</div>
);

// When showing isDisplayNone undefined -> false
<UserCard name='名前' />;
// When not showing isDisplayNone true
<UserCard name='名前' isDisplayNone />;

Enter fullscreen mode Exit fullscreen mode

4. Pay attention to import statement

/* NG🤔
├── Layout
    ├── Header.tsx
    └── Footer.tsx
*/
// page.tsx import files separately
import Header from './Layout/Header';
import Footer from './Layout/Footer';

/* Good🥴
├── Layout
    ├── Header.tsx
    ├── Footer.tsx
    └── index.tsx
*/
// index.tsx
export { default as Header } from './Header';
export { default as Footer } from './Footer';

// page.tsx import as a chunk
import { Footer, Header } from './Layout';

Enter fullscreen mode Exit fullscreen mode

Allow importing from the same path everywhere.

// NG:
import { Footer, Header } from '../../../../Layout';

// Good:😎
import { Footer, Header } from '@components/Layout';
Enter fullscreen mode Exit fullscreen mode

5. Make use of array methods

const data = [1,2,10]
const isIncludedNumber2 = data.includes(2);
const isIncludedNumber2Or3 = data.some((item) => item === 2 || item === 3);
const number3= data.find((item) => item === 3);
const numbersLargerThan2 = data.filter((item) => item > 2);
const totalNumber = data.reduce((sum, num) => sum + num, 0);
Enter fullscreen mode Exit fullscreen mode

6. Centerize how to manage unique values of the service

  • If values defined specifically for the service are written directly into the code, it becomes difficult to understand.
  • Is the code written in a way that prevents misunderstandings?
// NG🤔 status: What does the 0 mean?
const CheckStatus = (status: number) => {
  if (status === 0) {
    return true;
  }
  return false;
};

// Good🥴
const Status = {
  Invalid: 0,
  Valid: 1,
} as const;

type StatusLiteral = typeof Status[keyof typeof Status]; // 0 | 1

const CheckStatus = (status: StatusLiteral) => {
  if (status === Status.Invalid) {
    return true;
  }
  return false;
};

Enter fullscreen mode Exit fullscreen mode

Top comments (0)