How to re-render only one cell?

1.4k Views Asked by At

I am using react-table v7 and I'm running into an issue where when I change one cell's data, the entire table re-renders. I have thousands of rows, so re-rendering every time is pretty slow.

My react-table calls a form that the user can fill out to delete an item from a particular row: the form calls an API that changes the data in the backend.

I want to be able to just re-render the cell containing the associated locations for the article that I am editing, in order to reflect that I've deleted a location from that cell.

Articles    Associated Locations
Article 1   **Paris, Brazil**
Article 2   Idaho, Illinois

would become:

Articles    Associated Locations
Article 1   **Paris**
Article 2   Idaho, Illinois

such that I would only re-render the top right cell.

Simplified code:

App.js:

function App() {

  const columns = useMemo(
    () => [
      {
        columns: [
          {
            Header: "Article",
            accessor: "headline",
            Cell: row => (
              <div>
                {row.original.headline}
              </div>
            )
          },
          
          {
            Header: "Locations",
            id: "locations",
            Cell: ({ row }) => (
              <div>
                {row.original.tags}
              </div>
            )
          },
        ]
      }
    
    ],

    []
  );

  const [data, setData] = useState([]);

  
  useEffect(() => {
    (async () => {
      const result = await axios("/articles"); // fetch data from an API
      setData(result.data);
    })();
  }, []);

  return (
    <div className="App">
      <Table columns={columns} data={data} />
    </div>
  );
}
export default App;

App.js calls Table.js:

Table.js:

export default function Table({ columns, data }) {
 
  const {
    getTableProps,
    getTableBodyProps,
    headerGroups,
    prepareRow,

  } = useTable(
    {
      columns,
      data,
    },
  );
  
  const renderRowSubComponent = React.useCallback(({ row }) => {
    return (
      <>
      <DeleteForm id={row.original.article_id} row={row} ></DeleteForm>
      </>
    );
    }
  );

  // Render the UI for your table
  return (
    <>
      <div>
        <table {...getTableProps()}>
          <thead>
            {headerGroups.map(headerGroup => (
              <tr {...headerGroup.getHeaderGroupProps()}>
                {headerGroup.headers.map(column => (
                  <th
                    {...column.getHeaderProps(column.getSortByToggleProps())}
                    className={
                      column.isSorted
                        ? column.isSortedDesc
                          ? "sort-desc"
                          : "sort-asc"
                        : ""
                    }
                  >
                    {column.render("Header")}
                  </th>
                ))}
              </tr>
            ))}
          </thead>
          <tbody {...getTableBodyProps()}>
            {page.map((row, i) => {
              prepareRow(row);
          etc.

And Table.js has a DeleteForm, which I use to call an API that deletes a selected location from an article:

DeleteForm.js:

class DeleteForm extends Component {
  constructor(props){
    super(props);

    this.state = {
      article_id: 0,
      inputLoc: null,
      locations: [],
    };
  }
  
  onChange = e => {
    this.setState({inputLoc: e.target.value}, () => {
      console.log(this.state.inputLoc, 'inputLoc')
    })};

  deleteLocAssociation = () => {
    fetch...
    // API call that deletes the location in the backend
    this.setState({locations: APIResults})
  }

  componentDidMount(){
    if(this.state.inputLoc){
      this.deleteLocAssociation();
    }
  }

  render() {
    const row = this.props.row

    return (
      <Form onSubmit={this.deleteLocAssociation}>
        // Form for user to input a location
      </Form>
      

    )


  }
}

export default DeleteForm

I've been scoping out Stack Overflow and the closest questions I could find were:

Some places say that virtualization or pagination might help, but I do want to render everything in my table at first, since I have a search function to look up data and I want all data to be available.

0

There are 0 best solutions below