3

I know useEffect is the 'combination' of componentDidUpdate and componentDidMount? but since I have already passed in a dependency, why is it still load during the first load?

import React, { useState, useEffect } from "react";
import { Button, Table, Column } from "antd";

const initData = [
  {
    id: 1,
    name: "James"
  },
  {
    id: 2,
    name: "John"
  }
];

function MyTable({ changeDataFlag }) {
  const [data, setData] = useState(initData);

  useEffect(() => {
    setData(
      data.map(o => ({
        id: "Titus",
        name: "Paul"
      }))
    );
  }, [changeDataFlag]);

  return (
    <Table dataSource={data} rowKey={data => data.id}>
      <Column title="Id" dataIndex="id" />
      <Column title="Name" dataIndex="name" />
    </Table>
  );
}

export default MyTable;

I expect to see James and John on the table before I click update button

https://codesandbox.io/s/hello-antd-t29cs

4 Answers 4

3

By default useEffect run first time and then on change of dependencies.

You can do this,

useEffect(() => {
    if(changeDataFlag){
      setData(
        data.map(o => ({
          id: "Titus",
          name: "Paul"
        }))
      );
    }
}, [changeDataFlag]);
Sign up to request clarification or add additional context in comments.

2 Comments

this make sense
but changeDataFlag has to initialise anyways so it triggers this useEFfect ryt ?
0

In my opinion,I think you should put the change data logic into onclick event. In general,when you click button you will fetch data from server and change data.


import React, { useState, useEffect } from "react";
import { Button, Table, Column } from "antd";

function MyTable({ data }) {
  return (
    <Table dataSource={data} rowKey={data => data.id}>
     <Column title="Id" dataIndex="id" />
     <Column title="Name" dataIndex="name" />
    </Table>
  );
}

export default MyTable;

import React, { useState, useEffect } from "react";
import { render } from "react-dom";
import "antd/dist/antd.css";
import MyTable from "./MyTable";
import { Button } from "antd";
const initData = [
  {
    id: 1,
    name: "James"
  },
  {
    id: 2,
    name: "John"
  }
];

const App = () => {
  const [changeDataFlag, setChangeDataFlag] = useState(false);
  const [data, setData] = useState(initData);
  return (
    <div>
      <Button
        type="primary"
        onClick={() => {
          setData(
            data.map(o => ({
              id: "Titus",
              name: "Paul"
            }))
          );
        }}
      >
        change data source
      </Button>
      <MyTable data={data} />
    </div>
  );
};

render(<App />, document.getElementById("root"));

1 Comment

changeDataFlag is from other component, there's a reason for that
0

To avoid execution of your dependency useEffect at first page render then you have to use - useEffect with useRef . It only runs on next changes

import { useEffect, useRef, useState } from 'react';

function MyComponent() {
  const [data, setData] = useState('some data');
  const isFirstRender = useRef(true);

  useEffect(() => {
    if (isFirstRender.current) {
      isFirstRender.current = false;
      return;
    }
    console.log("This will not be called on first render");
  }, [data]);

  return <div>My Component</div>;
}

Comments

-2

a useEffect without target only enter one time, maybe helps, after you can make a useEffect only for updates

useEffect(() => {
    setData(
      data.map(o => ({
        id: "Titus",
        name: "Paul"
      }))
    );
  }, []);

2 Comments

empty depencies make useEffect run like componentDidMount
hes asking the converse of what you have said

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.