reactjs / react.dev

The React documentation website
https://react.dev/
Creative Commons Attribution 4.0 International
11.06k stars 7.55k forks source link

[Question - Beta docs] Is there TypeScript version of examples? #5593

Open kevinadhiguna opened 1 year ago

kevinadhiguna commented 1 year ago

Hi, I was looking at basic useReducer examples in the beta version of React docs and am wondering if there's TypeScript version of them.

In my opinion, it would be a great addition if it doesn't exist yet. Thanks in advance!

gaearon commented 1 year ago

Not at the moment, but we'd like to make an effort to add that. Requires solving some technical challenges.

kandoradev commented 1 year ago

@kevinadhiguna

I can try and provide an example! Maybe if a senior dev reads this they might have some corrections, however:

Typescript's main feature is it's static type system.

Basically, what STS means is that when we compile our code, variables must already have their types (boolean, string) defined.

When we analyze the JavaScript code in the example you asked about we see:

  1. A function including the hook; useReducer. This will affect age, by incrementing whatever number is received as input. name is changed according to user input:
function reducer(state, action) {
  switch (action.type) {
    case 'incremented_age': {
      return {
        name: state.name,
        age: state.age + 1
      };
    }
    case 'changed_name': {
      return {
        name: action.nextName,
        age: state.age
      };
    }
  }
  throw Error('Unknown action: ' + action.type);
}
  1. A React component that introduces 2 objects, name: Taylor and age: 42

const initialState = { name: 'Taylor', age: 42 };

  1. Callback functions,handleButtonClick and handleInputChange, which respond to the changes by useReducer to name and age by updating the screen. Likewise, including dispatch will allow for re-renders for states.
export default function Form() {
  const [state, dispatch] = useReducer(reducer, initialState);

  function handleButtonClick() {
    dispatch({ type: 'incremented_age' });
  }

  function handleInputChange(e) {
    dispatch({
      type: 'changed_name',
      nextName: e.target.value
    }); 
  }
  1. A return function:
  return (
    <>
      <input
        value={state.name}
        onChange={handleInputChange}
      />
      <button onClick={handleButtonClick}>
        Increment age
      </button>
      <p>Hello, {state.name}. You are {state.age}.</p>
    </>
  );
}

Converting the aforementioned to Typescript would look something like this:

import { useReducer } from 'react';

type State = { name: string, age: number };
type Action =
  | { type: 'incremented_age' }
  | { type: 'changed_name', nextName: string };

function reducer(state: State, action: Action): State {
  switch (action.type) {
    case 'incremented_age': {
      return {
        name: state.name,
        age: state.age + 1
      };
    }
    case 'changed_name': {
      return {
        name: action.nextName,
        age: state.age
      };
    }
    default: throw Error('Unknown action: ' + action.type);
  }
}

const initialState: State = { name: 'Taylor', age: 42 };

export default function Form() {
  const [state, dispatch] = useReducer(reducer, initialState);

  function handleButtonClick() {
    dispatch({ type: 'incremented_age' });
  }

  function handleInputChange(e: ChangeEvent<HTMLInputElement>) {
    dispatch({
      type: 'changed_name',
      nextName: e.target.value
    }); 
  }

  return (
    <>
      <input
        value={state.name}
        onChange={handleInputChange}
      />
      <button onClick={handleButtonClick}>
        Increment age
      </button>
      <p>Hello, {state.name}. You are {state.age}.</p>
    </>
  );
}

In any case, you might benefit from going example by example and working on re-writing each component with Typescript as an exercise. I might do the same!

0ldh commented 1 year ago

@kevinadhiguna I think this site will help you. React TypeScript Cheatsheet #usereducer