Categories
React Answers

How to Add Table Rows that are Selectable on Click with React Table?

Sometimes, we want to add table rows that are selectable on click with React Table

In this article, we’ll look at how to add table rows that are selectable on click with React Table.

Add Table Rows that are Selectable on Click with React Table

To add table rows that are selectable on click with React Table, we can customize the columns to add a checkbox to the left of the other items.

Then we can pass props to that to make it select the rows.

For instance, we can write:

import React from "react";
import { useTable, useRowSelect } from "react-table";
import namor from "namor";

const range = (len) => {
  const arr = [];
  for (let i = 0; i < len; i++) {
    arr.push(i);
  }
  return arr;
};

const newPerson = () => {
  return {
    firstName: namor.generate({ words: 1, numbers: 0 }),
    lastName: namor.generate({ words: 1, numbers: 0 }),
    age: Math.floor(Math.random() * 30)
  };
};

const makeData = (...lens) => {
  const makeDataLevel = (depth = 0) => {
    const len = lens[depth];
    return range(len).map((d) => {
      return {
        ...newPerson(),
        subRows: lens[depth + 1] ? makeDataLevel(depth + 1) : undefined
      };
    });
  };

return makeDataLevel();
};

const IndeterminateCheckbox = React.forwardRef(
  ({ indeterminate, ...rest }, ref) => {
    const defaultRef = React.useRef();
    const resolvedRef = ref || defaultRef;

React.useEffect(() => {
      resolvedRef.current.indeterminate = indeterminate;
    }, [resolvedRef, indeterminate]);

    return (
      <>
        <input type="checkbox" ref={resolvedRef} {...rest} />
      </>
    );
  }
);

function Table({ columns, data }) {
  const {
    getTableProps,
    getTableBodyProps,
    headerGroups,
    rows,
    prepareRow,
    selectedFlatRows,
    state: { selectedRowIds }
  } = useTable(
    {
      columns,
      data
    },
    useRowSelect,
    (hooks) => {
      hooks.visibleColumns.push((columns) => [
        {
          id: "selection",

          Header: ({ getToggleAllRowsSelectedProps }) => (
            <div>
              <IndeterminateCheckbox {...getToggleAllRowsSelectedProps()} />
            </div>
          ),

Cell: ({ row }) => (
            <div>
              <IndeterminateCheckbox {...row.getToggleRowSelectedProps()} />
            </div>
          )
        },
        ...columns
      ]);
    }
  );

  return (
    <>
      <table {...getTableProps()}>
        <thead>
          {headerGroups.map((headerGroup) => (
            <tr {...headerGroup.getHeaderGroupProps()}>
              {headerGroup.headers.map((column) => (
                <th {...column.getHeaderProps()}>{column.render("Header")}</th>
              ))}
            </tr>
          ))}
        </thead>
        <tbody {...getTableBodyProps()}>
          {rows.slice(0, 10).map((row, i) => {
            prepareRow(row);
            return (
              <tr {...row.getRowProps()}>
                {row.cells.map((cell) => {
                  return (
                    <td {...cell.getCellProps()}>{cell.render("Cell")}</td>
                  );
                })}
              </tr>
            );
          })}
        </tbody>
      </table>
      <p>Selected Rows: {Object.keys(selectedRowIds).length}</p>
      <pre>
        <code>
          {JSON.stringify(
            {
              selectedRowIds: selectedRowIds,
              "selectedFlatRows[].original": selectedFlatRows.map(
                (d) => d.original
              )
            },
            null,
            2
          )}
        </code>
      </pre>
    </>
  );
}

export default function App() {
  const columns = React.useMemo(
    () => [
      {
        Header: "Name",
        columns: [
          {
            Header: "First Name",
            accessor: "firstName"
          },
          {
            Header: "Last Name",
            accessor: "lastName"
          }
        ]
      },
      {
        Header: "Info",
        columns: [
          {
            Header: "Age",
            accessor: "age"
          }
        ]
      }
    ],
    []
  );

  const data = React.useMemo(() => makeData(10, 3), []);

  return <Table columns={columns} data={data} />;
}

We create some data with the makeData function, which calls newPerson to return some randomly generated data.

Then we create the IndeterminateCheckbox component that renders a checkbox that is assigned the ref that we get from the 2nd parameter.

We also pass in the rest props from the first parameter.

This will let us select rows with the checkbox.

Then in the Table component, we render the data.

We set the Header property to a function that renders the IndeterminateCheckbox with the props that we get from getToggleAllRowProps .

Likewise, we set the Cell property to a function that renders the IndeterminateCheckbox with the props that we get from getToggleRowSelectedProps .

We put that before columns so that it’ll be rendered on the leftmost column.

Then in the return statement, we render the table contents.

selectedRowIds has the IDs of the selected row.

And selectedFlatRows has the data of the selected rows.

Conclusion

To add table rows that are selectable on click with React Table, we can customize the columns to add a checkbox to the left of the other items.

Then we can pass props to that to make it select the rows.

Categories
React Answers

How to Poll an API Periodically with React?

Sometimes, we want to poll API periodically with React.

In this article, we’ll look at how to poll API periodically with React.

Poll an API Periodically with React

To poll API periodically with React, we can call the setInterval function to create a timer that lets us run code periodically.

For instance, we can write:

import React, { useEffect, useState } from "react";

export default function App() {
  const [answer, setAnswer] = useState();

  const getAnswer = async () => {
    const res = await fetch("https://yesno.wtf/api");
    const data = await res.json();
    setAnswer(data);
  };

  useEffect(() => {
    const timer = setInterval(getAnswer, 2000);
    return () => clearInterval(timer);
  }, []);

  return <div>{JSON.stringify(answer)}</div>;
}

We call the useState hook to create the answer state.

Then we create the getAnswer fucntion with the fetch function.

We call setAnswer with data to set the answer value.

Next, we call the useEffect hook with a callback that calls setInterval with the getAnswer function and 2000 to call getAnswer every 2000 milliseconds.

We also return a function that calls clearInterval to clear the timer when we unmount the component.

The empty array in the 2nd argument makes the useEffect callback only runs when the component mounts.

And then we render the answer as a string with JSON.stringify .

Conclusion

To poll API periodically with React, we can call the setInterval function to create a timer that lets us run code periodically.

Categories
React Answers

How to Detect Whether an Input Element is Focused within React?

Sometimes, we want to detect whether an input element is focused within React.

In this article, we’ll look at how to detect whether an input element is focused within React.

Detect Whether an Input Element is Focused within React

To detect whether an input element is focused within React, we can use a state to keep track of when the element is focused or not.

For instance, we can write:

import React from "react";

export default function App() {
  const [focused, setFocused] = React.useState(false);
  const onFocus = () => setFocused(true);
  const onBlur = () => setFocused(false);

  return (
    <>
      <input type="text" onFocus={onFocus} onBlur={onBlur} />
      <p>{focused.toString()}</p>
    </>
  );
}

We call the useState hook to create the focused state.

Then we creatr the onFocus and onBlur functions that calls setFocused with true and false respectively.

Then we set the onFocus function as the value of the onFocus prop which makes it run when we focus on the input.

And we set the onBlur prop to the onBlur function which makes it run when we move our focus away from the input.

Now when we click in and out of the input, we see true and false displayed if we focus in and out of the input respectively.

Conclusion

To detect whether an input element is focused within React, we can use a state to keep track of when the element is focused or not.

Categories
React Answers

How to use React-Intl’s FormattedMessage Component in an Input Placeholder?

Sometimes, we want to use React-Intl’s FormattedMessage component in an input placeholder.

In this article, we’ll look at how to use React-Intl’s FormattedMessage component in an input placeholder.

React-Intl’s FormattedMessage Component in an Input Placeholder

To use React-Intl’s FormattedMessage component in an input placeholder, we can call the intl.formatMessage method to return a string with the translated message.

For example, we can write:

import React from "react";
import { IntlProvider, useIntl } from "react-intl";

const messages = {
  message: "enter your name"
};

const ChildComponent = () => {
  const intl = useIntl();
  const placeholder = intl.formatMessage({ id: "message" });

  return <input placeholder={placeholder} />;
};

export default function App() {
  return (
    <IntlProvider messages={messages} locale="en" defaultLocale="en">
      <ChildComponent />
    </IntlProvider>
  );
}

We have the message object with the messages.

Then we have the ChildComponent component that calls the useIntl hook to get the intl object.

Then we call intl.formatMessage with an object that has the id property set to the key with the message to return the translated message.

And then we can set the returned string as the value of the placeholder .

Finally, we wrap IntlProvider around the ChildComponent so we can use the formatMessage method.

We set the messages to an object with the messages.

locale and defaultLocale are set to the locales.

Conclusion

To use React-Intl’s FormattedMessage component in an input placeholder, we can call the intl.formatMessage method to return a string with the translated message.

Categories
React Answers

How to Listen for Click Events that are Outside of a Component with React?

Sometimes, we want to listen for click events that are outside of a component with React.

In this article, we’ll look at how to listen for click events that are outside of a component with React.

Listen for Click Events that are Outside of a Component with React

To listen for click events that are outside of a component with React, we can call window.addEventListener to add a click event listener on the whole browser window.

For instance, we can write:

import React, { useEffect } from "react";

export default function App() {
  const pageClick = (e) => {
    console.log(e.target);
  };

  useEffect(() => {
    window.addEventListener("mousedown", pageClick);
  }, []);

  return <div></div>;
}

to create the pageClick function that logs e.target , which is a property with the element that we clicked on.

Then we can use that to listen for window clicks by calling window.addEventListener with 'mousedown' to listen to the mousedown event.

Now when we click anywhere in the browser window, we should see the element that we clicked on logged.

Conclusion

To listen for click events that are outside of a component with React, we can call window.addEventListener to add a click event listener on the whole browser window.