1. 14 Feb, 2020 2 commits
  2. 13 Feb, 2020 1 commit
  3. 11 Feb, 2020 1 commit
  4. 10 Feb, 2020 1 commit
  5. 08 Feb, 2020 3 commits
  6. 06 Feb, 2020 1 commit
  7. 03 Feb, 2020 1 commit
    • Lewis Llobera's avatar
      Change arrow functions to function declarations (#8412) · 687c4ebf
      Lewis Llobera authored
      - The JavaScript template uses a function declaration to define the component, the TypeScript template and a page of the documentation used arrow functions. Changed it to use function declarations for consistency and readability.
      687c4ebf
  8. 02 Feb, 2020 1 commit
  9. 31 Jan, 2020 17 commits
  10. 30 Jan, 2020 8 commits
  11. 23 Jan, 2020 1 commit
  12. 22 Jan, 2020 1 commit
    • Retsam's avatar
      Remove React.FC from Typescript template (#8177) · dada0357
      Retsam authored
      This removes `React.FC` from the base template for a Typescript project.
      
      Long explanation for a small change: 
      
      `React.FC` is unnecessary: it provides next to no benefits and has a few downsides.  (See below.)  I see a lot of beginners to TS+React using it, however, and I think that it's usage in this template is a contributing factor to that, as the prominence of this template makes it a de facto source of "best practice".  
      
      ### Downsides to React.FC/React.FunctionComponent
      
      ##### Provides an implicit definition of `children`
      
      Defining a component with `React.FC` causes it to implicitly take `children` (of type `ReactNode`).  It means that all components accept children, even if they're not supposed to, allowing code like:
      
      ```ts
      const App: React.FC = () => { /*... */ };
      const Example = () => {
      	<App><div>Unwanted children</div></App>
      }
      ```
      
      This isn't a run-time error, but it is a mistake and one that would be caught by Typescript if not for `React.FC`. 
      
      ##### Doesn't support generics.
      I can define a generic component like:
      ```ts
      type GenericComponentProps<T> = {
         prop: T
         callback: (t: T) => void
      }
      const GenericComponent = <T>(props: GenericComponentProps<T>) => {/*...*/}
      ```
      
      But it's not possible when using `React.FC` - there's no way to preserve the unresolved generic `T` in the type returned by `React.FC`.
      
      ```ts
      const GenericComponent: React.FC</* ??? */> = <T>(props: GenericComponentProps<T>) => {/*...*/}
      ```
      
      ##### Makes "component as namespace pattern" more awkward.
      It's a somewhat popular pattern to use a component as a namespace for related components (usually children):
      
      ```jsx
      <Select>
      	<Select.Item />
      </Select>
      ```
      
      This is possible, but awkward, with `React.FC`:
      
      ```tsx
      const  Select: React.FC<SelectProps> & { Item: React.FC<ItemProps> } = (props) => {/* ... */ }
      Select.Item = (props) => { /*...*/ }
      ```
      
      but "just works" without `React.FC`:
      
      ```tsx
      const Select = (props: SelectProps) => {/* ... */}
      Select.Item = (props) => { /*...*/ }
      ```
      
      ##### Doesn't work correctly with defaultProps
      
      This is a fairly moot point as in both cases it's probably better to use ES6 default arguments, but...
      
      ```tsx
      type  ComponentProps = { name: string; }
      
      const  Component = ({ name }: ComponentProps) => (<div>
      	{name.toUpperCase()} /* Safe since name is required */
      </div>);
      Component.defaultProps = { name: "John" };
      
      const  Example = () => (<Component />) /* Safe to omit since name has a default value */
      ```
      This compiles correctly.  Any approach with `React.FC` will be slightly wrong: either `React.FC<{name: string}>` will make the prop required by consumers, when it should be optional, or `React.FC<{name?: string}>` will cause `name.toUpperCase()` to be a type error.  There's no way to replicate the "internally required, externally optional" behavior which is desired.
      
      ##### It's as long, or longer than the alternative: (especially longer if you use `FunctionalComponent`):
      Not a huge point, but it isn't even shorter to use `React.FC` 
      ```ts
      const C1: React.FC<CProps> = (props) => { }
      const C2 = (props: CProps) => {};
      ```
      
      ### Benefits of React.FC
      
      ##### Provides an explicit return type
      
      The only benefit I really see to `React.FC` (unless you think that implicit `children` is a good thing) is that it specifies the return type, which catches mistakes like:
      
      ```ts
      const Component = () => {
         return undefined; // components aren't allowed to return undefined, just `null`
      }
      ```
      
      In practice, I think this is fine, as it'll be caught as soon as you try to use it:
      
      ```ts
      const Example = () => <Component />; // Error here, due to Component returning the wrong thing
      ```
      
      But even with explicit type annotations, `React.FC` still isn't saving very much boilerplate:
      
      ```ts
      const Component1 = (props: ComponentProps): ReactNode => { /*...*/ }
      const Component2: FC<ComponentProps> = (props) => { /*...*/ }
      ```
      dada0357
  13. 21 Jan, 2020 1 commit
  14. 16 Jan, 2020 1 commit