Skip to content

Gwenillia/some-h5p-usage

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

11 Commits
 
 
 
 

Repository files navigation

React.JS - H5P usage

This document serves as a guide for using and implementing React.JS within our codebase.

Table of Contents

Prerequisites

Developers with some JavaScript / React knowledge will familiarize very much easier.

Some useful Ressources

Main ressources

Optional ressources

Styling

We use Sass modules for styling our components. Each component should have its own Sass file located in the styles directory, mirroring the structure of the components directory.

File Organization

Our file tree should look closely to:

src
|- assets
|- components
|- context
|- helpers
|- hooks
|- styles
|- utils

The folders and files inside components and styles follow the same structure.

Each component directory should have an index.js file to export the component. This approach simplifies imports elsewhere in the application. No need to write the full path of a component to import it.

[!example] index.js structure

// One component to export from the folder
import Component from './Component';
export default Component
// Multiple components to export from the folder
import ComponentA from './ComponentA';
import ComponentB from './ComponentB';
export { ComponentA, ComponentB };

[!example] import in a component

// Without index.js
import Component from './components/Component/ComponentFile';
// With index.js
import Component from './components/Component';
// add {} if it is exported from an index.js exporting multiple component
import { Component } from './components/Common';

JavaScript will automatically look for an index.js file when you specify the path to a directory. This leads to cleaner and more readable code.

Additionnally, we use @ alias to simplify imports, which is setup through jsconfig.json and webpack.config.js at the root of the project. This alias represents the src directory.

[!example] import using @ alias

import { Component } from '@/components/Common'

This prevents to end up with multiple ../../ when you're importing inside a nested component from a totally different folder such as grand parents or uncles.

State Management

We use Context API and useReducer hook for managing state.

  • Context: allows use to pass data down to nested components without having to manually pass props at every level. This allows us to avoid "prop drilling" and makes our code cleaner and more maintainable

  • useReducer: For more complex state logic — such as the state machine in The Chase — we use the useReducer hook. This hook lets us manage state transitions in a more predictable way, through the use of actions and a reducer function.

Functional Components and Hooks

We primarily use functional components in conjunction with hooks.

Splitting Components

As your application grows, it might be helpful to start splitting components into smaller, reusable pieces. But how do you decide when to split a component? Here are some guidelines that can help:

  • Single Responsibility Principle: Each component should ideally do one thing. If it ends up growing, it should be split into smaller subcomponents.

  • Reusability: If a part of your UI is used in multiple places, it's a good idea to make it a separate component. This allows for code reuse and consistency across your app.

  • Complexity: If your component has too many lines of code or is becoming hard to understand, consider splitting it into smaller components. A good rule of thumb is if you have to scroll too much in your editor to see the entire component, it may be a sign that your component needs to be broken down.

  • State Logic: If a portion of your component has its own state or side effects (with hooks like useState or useEffect), it might be a good idea to split that part into its own component.

Remember, splitting components is an art. And be aware that smaller components are usually easier to maintain and test.

Testing

Ideally, we should be integrating more testing into our workflow. We use Jest and React Testing Library.

JSX

We write our React code in JavaScript and we use the JSX Syntax. Meaning that JavaScript expressions are embedded inside {}. JSX will convert HTML tags into React elements.

Here are some advantages of using JSX instead of JS:

  1. Readability and Simplicity: JSX makes our components easier to read and understand. It provides a clear picture of the DOM structure of a component, as it looks like regular HTML.

  2. Easy to Identify: In our codebase, we use .jsx extension for React components. This makes it easy to identify component files as opposed to other JavaScript files such as index.js in components folder or utility JavaScript files.

  3. Performance: JSX compiles into React.createElement() calls which is more efficient than creating elements with JavaScript and appending to the DOM.

  4. Components as HTML Elements: With JSX, we can use our custom components as if they were HTML elements, which makes the composition of our components a lot more intuitive.

Warning

Remember to import React in every JSX file:

import React from 'react';

PropTypes - Type Checking

To ensure the accuracy of props passed to components, we use PropTypes for type checking in our React codebase. PropTypes exports a range of validators that can be used to make sure the data you receive is valid.

[!example] Example of Type checking using PropTypes

import PropTypes from 'prop-types';

const Component = ({ name, age }) => {
  return (
    <div>
      <h1>{name}</h1>
      {age && <p>{age} yo</p>}
    </div>
  );
}

Component.propTypes = {
  name: PropTypes.string.isRequired,
  age: PropTypes.number,
}

export default Component;

Here, the Component expects to receive a name and an optional age. If name prop is not provided or it is of incorrect type, a warning will be shown in the JavaScript console. If age is provided but is not a number, a warning will also be shown. This helps us catching and fix problems earlier in development.

Best Practices

While working with our React.JS codebase, there are certain best practices to follow. Including:

  • One component = one file: In React, a component is a reusable piece of code that returns a React element to be rendered to the page. In our codebase, we adhere to the principle of "One Component Per File". This means that each .jsx file in our components directory defines exactly one React component. This makes it easy to understand the structure of our application and locate specific components.

  • Choosing useState versus useReducer: useState is enough for simple state management. For complex state logic such as a state machine, useReducer is a better choice.

  • Using Context: Context should be used to pass data down to nested components without having to manually pass props at every level.

  • Naming Conventions:

    • PascalCase: For the name of our components — both file name and the functional component itself —
    • camelCase: For the name of our variables.

Conclusion

This document should give you a better understanding of how we use React.js in our codebase.

About

small documentation referencing h5p usage of react

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published