teleren/devto huggingface dataset:
How to Make Select/Radio Component with React
Published: 2023-01-08 04:19:20

[✨ **Watch on YouTube**](https://youtu.be/o7V3vaIH7rM)  |  [🐙 GitHub](https://github.com/RodionChachura/react-toolkit)  |  [🎮 Demo](https://reactkit.radzion.com/select)

Here we can see a grid of options, where we can choose one by clicking on it or using arrows on the keyboard.

![](select.png)

To display an option, we are using the `SelectOption` component. It receives the same props as `InvisibleHtmlRadio` component plus children, and optional className. To make it accessible and support the keyboard, we use HTML radio input hidden from the user. It receives a group name that should be the same across a group of options, value, isSelected flag, onSelect callback, and optional autoFocus. To make it invisible we reset a bunch of attributes and position it absolutely.

```tsx
import React from "react"
import { ReactNode } from "react"
import styled, { css } from "styled-components"
import { defaultTransitionCSS } from "lib/ui/animations/transitions"
import { centerContentCSS } from "lib/ui/utils/centerContentCSS"

import { defaultInputShapeCSS } from "../config"
import {
  InvisibleHTMLRadio,
  Props as InvisibleHTMLRadioProps,
} from "../InvisibleHTMLRadio"

const Container = styled.label<{ isSelected: boolean }>`
  position: relative;
  cursor: pointer;

  ${centerContentCSS}
  background: ${({ theme }) => theme.colors.backgroundGlass.toCssValue()};

  ${defaultInputShapeCSS};
  ${defaultTransitionCSS};

  font-weight: 500;

  color: ${({ theme }) => theme.colors.textSupporting.toCssValue()};
  :hover {
    background: ${({ theme }) => theme.colors.backgroundGlass2.toCssValue()};
  }

  ${({ isSelected }) =>
    isSelected &&
    css`
      background: ${({ theme }) => theme.colors.backgroundGlass2.toCssValue()};
      color: ${({ theme }) => theme.colors.text.toCssValue()};
    `};
`

interface Props extends InvisibleHTMLRadioProps {
  children: ReactNode
  className?: string
}

export const SelectOption = ({
  isSelected,
  children,
  className,
  ...rest
}: Props) => {
  return (
    <Container className={className} tabIndex={-1} isSelected={isSelected}>
      {children}
      <InvisibleHTMLRadio isSelected={isSelected} {...rest} />
    </Container>
  )
}
```

For the container styles, we set position, cursor, center content, background, the same shape as an input element, transition, font-weight, color, and hover effect. To highlight the selected option we rely on the isSelected flag and set a different color for the background and text. Then we place children and invisible radio inside of the container, and we are good to go.

We can also use a different approach where we use one Select component instead of mapping over options and rendering SelectOption, but then we might lose some flexibility. For example, here, I want to display options in two rows and make the last one take two columns, and using a custom container makes it easy.
Tabs/View Selector Provider with React & TypeScript
Published: 2023-01-08 04:18:48

[✨ **Watch on YouTube**](https://youtu.be/aSiTQifBsAc)  |  [🐙 GitHub](https://github.com/RodionChachura/react-toolkit)  |  [🎮 Demo](https://reactkit.radzion.com/select-view)

It's a popular UI pattern to have a selector or tabs that change the content below. For simple situations, it's enough to store the view with the `useState` hook, but often children components need a selected view name with a function to change it, and we end up with either prop drilling or a state provider.

These providers take some code to set up, so let's write a function that will generate a boilerplate we can use to add new views and selectors. You can find both code and demo in the description.

Here's a simple example where we have two views, and we call a function that generates a provider, hook, and component for rendering the selected view. Below, we have a selector component to render view options. We place it under the ViewProvider together with the RenderView component that takes functions for every view to render the selected one.

The `getViewSetup` is a generic function that takes two arguments: default view and name of view group. First, we create an interface with the state and a context. The provider has a simple implementation where we store the selected view with the useState hook.

```tsx
import React from "react"
import { ReactNode, createContext, useState } from "react"
import { ComponentWithChildrenProps } from "lib/shared/props"

import { createContextHook } from "./createContextHook"

export function getViewSetup<T extends string | number | symbol>(
  defaultView: T,
  name: string
) {
  interface ViewState {
    view: T
    setView: (view: T) => void
  }

  const ViewContext = createContext<ViewState | undefined>(undefined)

  const ViewProvider = ({ children }: ComponentWithChildrenProps) => {
    const [view, setView] = useState<T>(defaultView)

    return (
      <ViewContext.Provider value={{ view, setView }}>
        {children}
      </ViewContext.Provider>
    )
  }

  const useView = createContextHook(ViewContext, `${name}ViewContent`)

  const RenderView = (props: Record<T, () => ReactNode>) => {
    const { view } = useView()
    const render = props[view]

    return <>{render()}</>
  }

  return {
    ViewProvider,
    useView,
    RenderView,
  }
}
```

To access provider value, we leverage the `createContextHook` that will throw an error if the provider is missing. Finally, we make the `RenderView` function that receives the render function for every view in the group and picks the one based on the useState hook.

```tsx
import { Context as ReactContext, useContext } from "react"

export function createContextHook<T>(
  Context: ReactContext<T | undefined>,
  contextName: string
) {
  return () => {
    const context = useContext(Context)

    if (!context) {
      throw new Error(`${contextName} is not provided`)
    }

    return context
  }
}
```
Measure Component Size with React and ResizeObserver
Published: 2023-01-08 04:18:16

[✨ **Watch on YouTube**](https://youtu.be/PQ7QKBz_zWE)  |  [🐙 GitHub](https://github.com/RodionChachura/react-toolkit)  |  [🎮 Demo](https://reactkit.radzion.com/size-aware)

The component takes only render prop, a function that receives a callback to set the target element and size of that element. We are using state instead ref for storing the HTML element so that we'll get a re-render on the value change. The component is a simple wrapper, and all the action is happening in the useElementSize hook.

```tsx
import { ReactNode, useState } from "react"

import { ElementSize, useElementSize } from "./hooks/useElementSize"

interface ElementSizeAwareRenderParams {
  size: ElementSize | null
  setElement: (element: HTMLElement | null) => void
}

interface Props {
  render: (params: ElementSizeAwareRenderParams) => ReactNode
}

export const ElementSizeAware = ({ render }: Props) => {
  const [element, setElement] = useState<HTMLElement | null>(null)

  const size = useElementSize(element)

  return <>{render({ setElement, size })}</>
}
```

The size interface has only the `width` and `height`. We can also take the element position from the bounding box, but it won't be reliable since `ResizeObserver` will only tell us about size changes. We pass only one argument to the `ResizeObserver`, a function to trigger when size changes. Here we extract width and height from the bounding box, check if they changed, and update the size state. We pass an element to observe to the observe method and call the disconnect method to stop listening for changes.

```tsx
import { pick } from "lib/shared/utils/pick"
import { useState } from "react"
import { useIsomorphicLayoutEffect } from "react-use"

export interface ElementSize {
  width: number
  height: number
}

const toElementSize = (rect: DOMRect): ElementSize =>
  pick(rect, "height", "width")

const areEqualSizes = (one: ElementSize, another: ElementSize) =>
  one.width === another.width && one.height === another.height

export const useElementSize = (element: HTMLElement | null) => {
  const [size, setSize] = useState<ElementSize | null>(() =>
    element ? toElementSize(element.getBoundingClientRect()) : null
  )

  useIsomorphicLayoutEffect(() => {
    if (!element) return

    const handleElementChange = () => {
      const newSize = toElementSize(element.getBoundingClientRect())

      if (size && areEqualSizes(newSize, size)) return

      setSize(newSize)
    }

    handleElementChange()

    if (!window?.ResizeObserver) return

    const resizeObserver = new ResizeObserver(handleElementChange)

    resizeObserver.observe(element)

    return () => {
      resizeObserver.disconnect()
    }
  }, [element])

  return size
}
```

To update the size state after the dom has changed, we are using the `useLayoutEffect` hook because the `useEffect` will wait until the rerender, and we might end up with flickers.
JavaScript Strict Mode
Tags: javascript
Published: 2023-03-03 16:34:31

---
title: JavaScript Strict Mode
published: true
date: 2023-01-05 18:00:00 UTC
tags: JavaScript
canonical_url: https://www.90-10.dev/js-strict-mode/
---

JavaScript Strict Mode is a crucial aspect of writing efficient and secure code. It was introduced in ECMAScript 5 (ES5) to address some of the issues of the language's "sloppy mode" and enforces stricter rules for JavaScript code, making it more secure and less prone to errors.

### All variables must be declared

One of the main features of Strict Mode is that it prevents the use of undeclared variables. This means that any variable that has not been explicitly declared with the `var`, `let`, or `const` keywords will result in an error. This helps catch potential errors early on and encourages developers to write more organized and maintainable code.

### Disabled Features

Strict Mode also disables certain features that are considered to be problematic, such as `with` statements and implicit global variables. This helps prevent common mistakes that can lead to security vulnerabilities and other issues.

## Enable globally

```
'use strict';
x = 42;

```

> Error - x is not declared

NB: The `'use strict'` statement will be ignored by old browsers that don't support strict mode.

## Limited strict

Strict mode can be enabled in a local context - eg: inside a function:

```
x = 42;

```

> No Error (strict mode not on here)

```
function myFunction() {
  'use strict';
  y = 42;
}
```

> Error - y is not declared

* * *

The use of JavaScript Strict Mode is highly recommended for any JavaScript project. It can help catch errors early on, prevent common mistakes, and make code more secure and maintainable.

## Reading List

- [MDN page](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode)
- [w3schools page](https://www.w3schools.com/js/js_strict.asp)
Make Combobox / Dropdown Input with React & TypeScript
Published: 2023-01-08 04:17:12

[✨ **Watch on YouTube**](https://youtu.be/iZGQE3-pqpg)  |  [🐙 GitHub](https://github.com/RodionChachura/react-toolkit)  |  [🎮 Demo](https://reactkit.radzion.com/combobox)

Let's make a text input with fixed options, where the user gets suggestions while typing, but they can only "submit" the field with a value from the list of options. Here, we have an example of an input where you can select languages you know.

![](combobox.png)

The `LanguagesInput` component receives an array of selected languages, the `onChange` callback, and an optional error message. It consists of two parts: the `FixedOptionsInput` and a list of entered languages. The most sophisticated piece here is the `Combobox` component. First, we pass properties common to form fields: label, placeholder, error, ref, onChange, and value, which is null because we don't preselect any value. Then we provide options that could be of any type, so we follow with a string convertor. To clear the input after choosing a language, we pass the `clearAfterOptionSelected` flag. We can also provide a render option function to display a custom element in the list of suggestions.

```tsx
<FixedOptionsInput
  label="Languages"
  placeholder="Spanish"
  value={null}
  ref={ref}
  onChange={(value) => {
    if (value) {
      handleAddLanguage(value)
    }
  }}
  error={error}
  optionToString={(option) => option}
  options={availableLanguageNames}
  clearAfterOptionSelected
/>
```

The parent element for the combo box is a div, for which we set up `ref`, and the onBlur callback to close the menu when inner elements are out of focus. Then we have an input wrapper for providing a label and error message together with an absolutely positioned button to toggle men open state. I covered both the InputWrapperWithErrorMessage and `TextInputContainer` in [another post](/blog/inputs).

To display suggestions, we have the `DropdownMenuPlacer` component. We pass input as children and a list of options to the placer, and it sets up refs to position the menu right under the input. To show the menu with are using the react-popper library. Here we set up a config to show the menu on top in case there is not enough space, then we add a margin between the input and the menu. Finally, we make the menu the same width as the input.

The `ComboboxOptions` component takes a list of suggestions and renders them inside a container that sets a specific max height together with overflow-y set to auto to show a scroll. We store refs of every option to scroll into view a selected one. To allow moving between suggestions with keyboards, we are using a combination of the user keypress hook together with the getHandleStep function.

The `FixedOptionsInput` has some tricky effects managing input and menu with suggestions. We won't go deep into them, but if you're curious, welcome to explore them on GitHub.
How to make Button Variants with React, TypeScript and Styled Components
Tags: react, typescript
Published: 2023-01-08 04:13:59

[✨ **Watch on YouTube**](https://youtu.be/K5y_irnv34s)  |  [🐙 GitHub](https://github.com/RodionChachura/react-toolkit)  |  [🎮 Demo](https://reactkit.radzion.com/button)

Most apps have three types of buttons: primary, ghost, and outlined. Let's make those buttons with React, TypeScript, and styled-components so we can take them to a new project, change a few styles, and we are good to go!

To have less code, we'll build these buttons on top of the RectButton component. It can receive all of the button attributes and children. We allow rendering it as a div element. It's handy when we want to show a button inside an anchor element. Then there is a size property ranging from xs to xl; and three flags: disabled, loading, and rounded.

The component itself is simple. We render either spinner or children inside of the styled container. The container wraps the UnstyledButton to not drug unnecessary styles. First, we set the color to the text color, then we assign border-radius, simple transition, and center the content. Based on the size property, the button will have different horizontal padding, height, and font size. Then we set cursor and opacity based on flags.

With all basic styles defined on the RectButton, we can easily extend it to different types of buttons. The Primary button has only one extra property - kind. Based on this property, we'll choose background and hover. To not brake the component, we don't assign as to the container but rather propagate it to the RectButton component with the forwardAs property.

The ghost button also has a kind property that defines text color. The outlined button doesn't have variants and only changes the border and background properties of the base button.
How to make Table with CSS Grid and React
Tags: react, typescript
Published: 2023-01-08 04:13:27

[✨ **Watch on YouTube**](https://youtu.be/oVnpdHiI30E)  |  [🎮 Demo](https://reactkit.radzion.com/grid-table)

The `<table>` tag is not the most friendly HTML element, but hopefully, we can build a simple table layout with a CSS grid!

![](/grid.png)

The `TableLayout` component receives `gridTemplateColumns` CSS attribute, a list of column names and children. Then we make every row contain the same number of elements as the column names array. The table's container is a grid element with aligned items to which we pass the grid template column with the style attribute.

```tsx
import { CSSProperties } from "react"
import { ComponentWithChildrenProps } from "shared/props"
import styled from "styled-components"
import { Line } from "ui/Line"
import { Text } from "ui/Text"

interface Props extends ComponentWithChildrenProps {
  columnNames: string[]
  gridTemplateColumns: CSSProperties["gridTemplateColumns"]
}

const Container = styled.div`
  display: grid;
  gap: 16px 48px;
  align-items: center;
`

const Separator = styled(Line)`
  grid-column: 1/-1;
`

export const TableLayout = ({
  children,
  columnNames,
  gridTemplateColumns,
}: Props) => {
  return (
    <Container style={{ gridTemplateColumns }}>
      {columnNames.map((name) => (
        <Text weight="regular" color="supporting3" key={name}>
          {name}
        </Text>
      ))}
      <Separator />
      {children}
    </Container>
  )
}
```

We iterate over the array of column names and render them with the Text component. To span the separator line over the whole row, we use the grid-column property that starts with the first element and ends with the last. Finally, we display children, and we are good to go!
AWS Secrets Manager & NodeJS AWS Lambda & Terraform
Tags: aws, node, typescript
Published: 2023-01-08 04:10:42

[✨ **Watch on YouTube**](https://youtu.be/5_6GuaC36ZA)

Let's use AWS Secrets Manager with AWS Lambda to keep the secrets safe.

To manage infrastructure, I use Terraform, but you can do the same through AWS CLI or web interface. One caveat is that I don't assign the secrets in Terraform because we don't want secrets in Terraform's state files. Instead, I do that through the AWS web interface. Here I create variables. Then I make a policy to allow Lambda read those variables and finally attach that policy to Lambda's IAM.

```hcl
resource "aws_secretsmanager_secret" "auth_secret" {
  name = "twitter_client_secret"
}

resource "aws_secretsmanager_secret" "google_client_secret" {
  name = "storybot_mnemonic_key_staging"
}

resource "aws_iam_policy" "secrets" {
  name = "tf-${var.name}-secrets"
  path = "/"

  policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "secretsmanager:GetSecretValue",
      "Resource": "${aws_secretsmanager_secret.auth_secret.arn}",
      "Effect": "Allow"
    },
    {
      "Action": "secretsmanager:GetSecretValue",
      "Resource": "${aws_secretsmanager_secret.google_client_secret.arn}",
      "Effect": "Allow"
    }
  ]
}
EOF
}

resource "aws_iam_role_policy_attachment" "secrets" {
  role       = module.api.lambda_iam_role_name
  policy_arn = aws_iam_policy.secrets.arn
}
```

To make the Lambda know the names of those secrets, we can pass them as environment variables to the lambda.

```hcl
  environment {
    variables = {
      GOOGLE_CLIENT_SECRET_ASM_NAME = aws_secretsmanager_secret.google_client_secret.name
      AUTH_SECRET_ASM_NAME          = aws_secretsmanager_secret.auth_secret.name
    }
  }
```

To assess those env variables with the names of secrets, I use the assertEnvVar function that will throw an error if the variable is missing.

```ts
type VariableName = "GOOGLE_CLIENT_SECRET_ASM_NAME" | "AUTH_SECRET_ASM_NAME"

export const assertEnvVar = (name: VariableName): string => {
  const value = process.env[name]
  if (!value) {
    throw new Error(`Missing ${name} environment variable`)
  }

  return value
}
```

To get the secrets themselves, I have the assertSecret function that receives an argument of SecretName type, takes the variable name through the assertEnvVar function, and uses an instance of SecretsManager to get the value.

```hcl
import { SecretsManager } from "aws-sdk"
import { memoize } from "lodash"
import { assertEnvVar } from "./assertEnvVar"

type SecretName = "GOOGLE_CLIENT_SECRET" | "AUTH_SECRET"

const secretsManagerClient = new SecretsManager()

export const assertSecret = memoize(
  async (name: SecretName): Promise<string> => {
    const secretAsmName = assertEnvVar(`${name}_ASM_NAME`)

    const { SecretString: value } = await secretsManagerClient
      .getSecretValue({ SecretId: secretAsmName })
      .promise()

    if (!value) {
      throw new Error(`Missing ${secretAsmName} secret`)
    }
    return value
  }
)
```
How to Use Environment Variables in React App?
Tags: react, typescript
Published: 2023-01-08 04:10:10

[✨ **Watch on YouTube**](https://youtu.be/iwzD7CdhnIM)

How to gracefully use environment variables in React app? Let me show you pretty quickly.

I access environment variables through a single source - the `assertEnvVar` function. The function will throw an error if there is no such variable.

```ts
type VariableName = "SENTRY_KEY" | "API_URL" | "VERSION"

export const assertEnvVar = (name: VariableName): string => {
  const envVarName = `REACT_APP_${name}`
  const value = process.env[envVarName]
  if (!value) {
    throw new Error(`Missing ${envVarName} environment variable`)
  }

  return value
}
```

The `process.env` is an object with environment variables. But we don't want all environment variables in the bundle for the whole world to see. I use `create-react-app`, and it will export only variables starting with `REACT_APP_`. Different starters and frameworks have different prefixes. For example, Vite will have a `VITE_` prefix.

To not misspell the environment variable name, we have a union type instead of a string type for the name argument of the function. Those names do not include the `REACT_APP_` prefix, so the keys are shorter. If I change frontend tooling, I would only need to update the prefix in one place instead of going through every function call.

For local development, I declare environment variables in the `.env` file. For production, I set them before deploying a new version. You can also set environment variables in a script. I do that to access `package.json's` version in the app.

```json
"start": "REACT_APP_VERSION=$npm_package_version react-scripts start"
```