Vocabulary: Model-View-Controller (MVC)

MVC (Model-View-Controller):

MVC is a design pattern commonly used in software development to organize the structure of an application. It divides an application's components into three main parts:

Model: The Model represents the data and the logic to manipulate that data. It's responsible for managing the application's data and business logic. This can include data storage, retrieval, validation, and other operations that deal with the data itself.

View: The View is responsible for presenting the data to the user. It displays the information and interacts with the user interface. The View is often concerned with how the data is displayed and doesn't contain the business logic.

Controller: The Controller acts as an intermediary between the Model and the View. It receives input from the user through the View, processes that input by interacting with the Model, and updates the View accordingly. The Controller handles user interactions and orchestrates the flow of data and actions between the Model and the View.

(from ChatGPT)

Vocabulary: Call signature

A call signature in TypeScript is a way to define the type of a function or method within an interface or type. It specifies the shape of a function, including the parameter types and the return type. This allows you to describe the signature of functions that can be called, including their arguments and return values. (from ChatGPT)

interface MyFunction {
  (param1: number, param2: string): boolean;
}

const myFunc: MyFunction = (num, str) => {
  return num > parseInt(str);
};

console.log(myFunc(5, '3')); // Output: true

Vocabulary: Index signature

In TypeScript, an index signature (also known as an indexable type) allows you to define the types of properties that are not known in advance but can be accessed using square bracket notation. Index signatures are particularly useful when working with objects that have dynamic property names. (from ChatGPT)

interface MyObject {
  [key: string]: number;
}

const myData: MyObject = {
  apple: 5,
  banana: 3,
};

console.log(myData.apple); // Output: 5
console.log(myData.banana); // Output: 3

Vocabulary: Higher-Order Component (HOC)

A design pattern used in React that is a function that takes in a component and returns a new component. (getting all this from ChatGPT)

import React from 'react';

function Greeting(props) {
  return <h1>Hello, {props.name}!</h1>;
}

export default Greeting;
import React from 'react';

function withBorder(Component) {
  return function(props) {
    return (
      <div style={{ border: '2px solid black', padding: '10px' }}>
        <Component {...props} />
      </div>
    );
  };
}

export default withBorder;
import React from 'react';
import Greeting from './Greeting';
import withBorder from './withBorder';

// Using the HOC to enhance the component
const EnhancedGreeting = withBorder(Greeting);

function App() {
  return (
    <div>
      <Greeting name="Alice" />
      <EnhancedGreeting name="Bob" />
    </div>
  );
}

export default App;

or something like

import React from 'react';

const withLoading = (WrappedComponent) => {
  return (props) => {
    const { isLoading, ...restProps } = props;

    if (isLoading) {
      return <div>Loading...</div>; // Display a loading indicator
    } else {
      return <WrappedComponent {...restProps} />;
    }
  };
};

export default withLoading;
import React from 'react';
import withLoading from './withLoading';

const DataComponent = ({ data }) => {
  return (
    <div>
      <h1>Data Component</h1>
      <p>{data}</p>
    </div>
  );
};

export default withLoading(DataComponent);
import React, { useState, useEffect } from 'react';
import DataComponent from './DataComponent';

const App = () => {
  const [isLoading, setIsLoading] = useState(true);
  const [data, setData] = useState('');

  useEffect(() => {
    // Simulate an asynchronous operation (e.g., fetching data)
    setTimeout(() => {
      setData('Fetched data');
      setIsLoading(false);
    }, 2000);
  }, []);

  return (
    <div>
      <h1>App</h1>
      <DataComponent isLoading={isLoading} data={data} />
    </div>
  );
};

export default App;

React: Generic Type

type ExampleComponentProps<T extends React.ReactElement> = {
  children: T;
};

const ExampleComponent = <T extends React.ReactElement>({ children }: ExampleComponentProps<T>): React.ReactElement => {
  if ('onClick' in children.props) {
    console.log("children has an onClick prop");
  }

  return <div>{children}</div>;
};

・By using T extends React.ReactElement, the children prop of ExampleProps can accept any React element as its value.
・The component can receive the props of the children (ie: onClick).

Testing Notes

-Unit Testing
・The testing of individual blocks of an application such as a class, function, or component.

-Integration Testing
・Testing a combination of units and ensuring they work together.

-E2E Testing
・Testing the entire application flow and ensuring it works as designed from start to finish

-What to test
・component renders
・component renders with props
・component renders with different states
・component reacting to events

-How to test
1. Render component
2. Find element rendered
3. Assert element (using expect with matcher) which will pass or fail

-RTL Queries
・find single element
    -getBy
    -queryBy
    -findBy
・find multiple elements
    -getAllBy
    -queryAllBy
    -findAllBy

-How to write tests

hoge.test.ts

describe(“testing”, () => {
  test(“renders correctly”, => {
    render(<Component/>)
    ….queries
  }) 
})

Prettier & Eslint format

package.json

  "scripts": {
    "prettier": "prettier --write --ignore-path .gitignore './**/*.{js,jsx,ts,tsx,json}'",
    "lint": "eslint --fix . --ext js --ext jsx",
    "format": "eslint --fix . --ext js --ext jsx && prettier --write --ignore-path .gitignore './**/*.{js,jsx,ts,tsx,json}'"  },
 ...., 
 "prettier": {
    "printWidth": 100,
    "tabWidth": 2,
    "useTabs": false,
    "semi": true,
    "singleQuote": false,
    "quoteProps": "as-needed",
    "trailingComma": "all",
    "bracketSpacing": true,
    "bracketSameLine": false,
    "arrowParens": "always"
  }
}