当任何函数为 运行 时,useEffect 为 运行

useEffect is running when any function is running

首先,我对这个问题进行了很多研究,但找不到解决方案。如果您能提供帮助,我将不胜感激。

功能组件

我在下面简单地添加了代码。这不是完整代码

状态和道具

  // blog id
  const { id } = props.match.params;

  // state
  const initialState = {
    title: "",
    category: "",
    admin_id: "",
    status: false
  };

  const [form, setState] = useState(initialState);
  const [adminList, setAdminList] = useState([]);
  const [articleText, setArticleText] = useState([]);
  const [me, setMe] = useState([]);
  const [locked, setLocked] = useState(true);
  const timerRef = useRef(null);

// queries and mutations 

  const { loading, error, data } = useQuery(GET_BLOG, {
    variables: { id }
  });

  const { data: data_admin, loading: loading_admin } = useQuery(GET_ADMINS);

  const [editBlog, { loading: loadingUpdate }] = useMutation(
    UPDATE_BLOG
  );
  const [lockedBlog] = useMutation(LOCKED_BLOG);

多种使用效果和功能

useEffect(() => {
    if (!loading && data) {
      setState({
        title: data.blog.title,
        category: data.blog.category,
        admin_id: data.blog.admin.id,
        status: data.blog.status
      });
      setArticleText({
        text: data.blog.text
      });
    }
    console.log(data);
  }, [loading, data]);

  useEffect(() => {
    if (!loading_admin && data_admin) {
      const me = data_admin.admins.filter(
        x => x.id === props.session.activeAdmin.id
      );
      setAdminList(data_admin);
      setMe(me[0]);
    }
  }, [data_admin, loading_admin]);

  useEffect(() => {
    const { id } = props.match.params;
    lockedBlog({
      variables: {
        id,
        locked: locked
      }
    }).then(async ({ data }) => {
      console.log(data);
    });
    return () => {
      lockedBlog({
        variables: {
          id,
          locked: false
        }
      }).then(async ({ data }) => {
        console.log(data);
      });
    };
  }, [locked]);

  // if loading data
  if (loading || loading_admin)
    return (
      <div>
        <CircularProgress className="loadingbutton" />
      </div>
    );

  if (error) return <div>Error.</div>;

  // update onChange form
  const updateField = e => {
    setState({
      ...form,
      [e.target.name]: e.target.value
    });
  };

  // editor update
  const onChangeEditor = text => {
    const currentText = articleText.text;
    const newText = JSON.stringify(text);
    if (currentText !== newText) {
      // Content has changed
      if (timerRef.current) {
        clearTimeout(timerRef.current);
      }
      setArticleText({ text: newText });
      if (!formValidate()) {
        timerRef.current = setTimeout(() => {
          onSubmitAuto();
        }, 10000);
      }
    }
  };

  // auto save
  const onSubmitAuto = () => {
    if (timerRef.current) {
      clearTimeout(timerRef.current);
    }
    editBlog({
      variables: {
        id,
        admin_id,
        title,
        text: articleText.text,
        category,
        status
      }
    }).then(async ({ data }) => {
      console.log(data);
    });
  };

  // validate

  const formValidate = () => {
    const { title, category } = form;
    return !title || !articleText.text || !category;
  };

  // clear state
  const resetState = () => {
    setState({ ...initialState });
  };

  return (
    // jsx
  )

第一期,调用onSubmitAuto时,第一个useEffect又是运行。我不想要这个。 因为我只想让它在第一次安装时工作。

第二个问题,如果articleText状态之前发生过变化,当突变时它不会突变表单状态中的数据。但是如果表单状态先改变,它会改变所有数据。我觉得这期和第一期一样。

希望能说明问题。 :/

再见,第一个问题我有一个答案:当onSubmitAuto被触发时,它调用editBlog改变loadingloading 在第一个 useEffect 部门列表中。 如果您不想这样,修复方法可能是这样的:

const isInitialMount = useRef(true);
//first useEffect
useEffect(() => {
if(isInitialMount.current) {
if (!loading && data) {
  setState({
    title: data.blog.title,
    category: data.blog.category,
    admin_id: data.blog.admin.id,
    status: data.blog.status
  });
  setArticleText({
    text: data.blog.text
  });
}
console.log(data);
if (data !== undefined) isInitialMount.current = false;
}
}, [loading, data]);