Javascript 当任何函数正在运行时,useEffect正在运行

Javascript 当任何函数正在运行时,useEffect正在运行,javascript,reactjs,graphql,apollo,apollo-client,Javascript,Reactjs,Graphql,Apollo,Apollo Client,首先,我对这个问题做了很多研究,但没有找到解决办法。如果你能帮忙,我将不胜感激 功能部件 我在下面简要地添加代码。这不是完整的代码 状态和道具 // blog id const { id } = props.match.params; // state const initialState = { title: "", category: "", admin_id: "", status

首先,我对这个问题做了很多研究,但没有找到解决办法。如果你能帮忙,我将不胜感激

功能部件

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

状态和道具

  // 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
  )
useffect(()=>{
如果(!正在加载&数据){
设定状态({
标题:data.blog.title,
类别:data.blog.category,
管理员id:data.blog.admin.id,
状态:data.blog.status
});
setArticleText({
text:data.blog.text
});
}
控制台日志(数据);
},[加载,数据];
useffect(()=>{
如果(!加载管理和数据管理){
const me=data\u admin.admins.filter(
x=>x.id==props.session.activeAdmin.id
);
setAdminList(数据管理);
setMe(me[0]);
}
},[数据管理,加载管理];
useffect(()=>{
const{id}=props.match.params;
锁定博客({
变量:{
身份证件
锁定:锁定
}
}).then(异步({data})=>{
控制台日志(数据);
});
return()=>{
锁定博客({
变量:{
身份证件
锁定:错误
}
}).then(异步({data})=>{
控制台日志(数据);
});
};
},[锁定];
//如果加载数据
if(加载| |加载|管理)
返回(
);
如果(错误)返回错误。;
//更改表格后更新
常数updateField=e=>{
设定状态({
…形式,
[e.target.name]:e.target.value
});
};
//编辑器更新
const onchangeditor=text=>{
const currentText=articleText.text;
const newText=JSON.stringify(text);
如果(currentText!==newText){
//内容发生了变化
if(定时器参考电流){
clearTimeout(timerRef.current);
}
setArticleText({text:newText});
如果(!formValidate()){
timerRef.current=设置超时(()=>{
onSubmitAuto();
}, 10000);
}
}
};
//自动保存
const onSubmitAuto=()=>{
if(定时器参考电流){
clearTimeout(timerRef.current);
}
编辑博客({
变量:{
身份证件
管理员id,
标题
text:articleText.text,
类别
地位
}
}).then(异步({data})=>{
控制台日志(数据);
});
};
//证实
const formValidate=()=>{
const{title,category}=形式;
return!title | |!articleText.text | |!category;
};
//清晰状态
常量重置状态=()=>{
setState({…initialState});
};
返回(
//jsx
)
第一个问题,当调用SubmitAuto时,first useEffect再次运行。我不要这个。 因为我只想让它在第一次安装时工作

第二个问题,如果
articleText
状态以前发生过更改,则在进行变异时不会对表单状态中的数据进行变异。但是,如果表单状态先更改,则会对所有数据进行变异。我觉得这个问题和第一个问题是一样的


我希望我能解释一下这个问题/

Ciao,我对第一个问题有一个答案:当触发
onSubmitAuto
时,它调用
editBlog
,更改
加载
。并且
加载
在第一个
useffect
deps列表中。 如果您不希望这样,修复可能是这样的:

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]);

再见,我对第一个问题有一个答案:当
onSubmitAuto
被触发时,它调用
editBlog
,从而更改
加载
。并且
加载
在第一个
useffect
deps列表中。 如果您不希望这样,修复可能是这样的:

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]);

首先,当你调用SubmitAuto时,它会再次运行上一个useEffect,因为useEffect已经[locked],你每次更改SubmitAuto上锁定的状态时,它都会运行上一个useEffect。我对锁定没有问题,我从onSubmitAuto上删除了锁定。同样的问题还在继续。我更新了代码。问题在于onSubmitAuto和第一个useEffect@Fernandoramirez首先,当你调用SubmitAuto时,它会再次运行上一个useEffect,因为useEffect已经[锁定],你每次更改SubmitAuto上锁定的状态时,锁定的状态都会运行上一个useEffect。我对锁定没有问题,我从onSubmitAuto上删除了锁定。同样的问题还在继续。我更新了代码。问题在于onSubmitAuto和第一个useEffect@Fernandoramirez感谢您的回答,但是现在setState在第一次加载时不起作用,所以useEffect现在不起作用。当我测试此代码时,“console.log(data)”返回未定义@乔瓦尼·埃斯波西西奥,如果在我的建议之前工作过,也应该在我的建议之后工作。我所做的只是使用bool ref在useffect中执行一次代码。真奇怪。。。如果(!loading&&data)返回false且setState将不执行,则不管怎样,如果数据为null。旧代码在控制台中也有一次未定义,然后数据出现。如何使useQuery数据异步?我不知道这一点,但useEffect正在尝试在装载数据后立即获取数据。旧代码正确加载数据。但是正如我所说,它给出了一次未定义的结果。谢谢你的回答,但是现在setState在第一次加载时不起作用,所以useEffect现在不起作用。当我测试这段代码时,“console.log(data)”返回未定义@乔瓦尼·埃斯波西西奥,如果在我的建议之前工作过,也应该在我的建议之后工作。我所做的只是使用bool ref在useffect中执行一次代码。真奇怪。。。如果(!loading&&data)返回false且setState将不执行,则不管怎样,如果数据为null。旧代码在控制台中也有一次未定义,然后数据出现。如何使useQuery数据异步?我不知道这一点,但useEffect正在尝试在装载数据后立即获取数据。旧代码正确加载数据。但正如我所说,它给出了一个未定义的定义。