Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cocoa/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Reactjs 如何在初始useEffect之后跳过特定useEffect_Reactjs_React Hooks - Fatal编程技术网

Reactjs 如何在初始useEffect之后跳过特定useEffect

Reactjs 如何在初始useEffect之后跳过特定useEffect,reactjs,react-hooks,Reactjs,React Hooks,我有以下代码,如何防止在初始渲染时调用AsyncStorage.setItem?它通过[]和从AsyncStorage加载的任何内容调用,因为日志已更新。完美的解决方案根本不应该调用setItem,因为日志刚刚从异步存储中检索 const AsyncStorage = require("@react-native-community/async-storage") const useStore = () => { const [logs, setLogs] = u

我有以下代码,如何防止在初始渲染时调用
AsyncStorage.setItem
?它通过
[]
和从
AsyncStorage
加载的任何内容调用,因为
日志
已更新。完美的解决方案根本不应该调用
setItem
,因为
日志
刚刚从
异步存储
中检索

const AsyncStorage = require("@react-native-community/async-storage")

const useStore = () => {
  const [logs, setLogs] = useState([])

  useEffect(() => {
    AsyncStorage.getItem("logs").then((newLogs) => setLogs(newLogs));
  }, [])

  useEffect(() => {
    //Don't want to setItem on initial load or when `logs` was just loaded.
    AsyncStorage.setItem("logs", JSON.stringify(logs));
  }, [logs])

  const addLog = (newText) => {
    setLogs(logs => [
      {text: newText, createdAt: new Date().getTime()},
      ...logs,
    ]);
  }

  return {
    logs,
    addLog,
    //...many other functions that update logs
  }
}

您可以使用ref作为是否允许设置日志的标志

const AsyncStorage = require("@react-native-community/async-storage")

const useStore = () => {
  const [logs, setLogs] = useState([]);
  const allowSettingLogs = React.useRef(false);

  useEffect(() => {
    AsyncStorage.getItem("logs").then((newLogs) => setLogs(newLogs));
  }, [])

  useEffect(() => {
    //Don't want to setItem on initial load or when `logs` was just loaded.
    if (allowSettingLogs.current) AsyncStorage.setItem("logs", JSON.stringify(logs));
  }, [logs])

  const addLog = (newText) => {
    allowSettingLogs.current = true;
    setLogs(logs => [
      {text: newText, createdAt: new Date().getTime()},
      ...logs,
    ]);
  }

  return {
    logs,
    addLog,
    //...many other functions that update logs
  }
}


您可能希望包装
useffect
,并使其忽略第一个更改

const useffectigningfirstchange=(fn,deps)=>{
const firstCallRef=useRef(true);
useffect(()=>{
if(firstCallRef.current){
firstCallRef.current=false;
返回;
};
fn()
},副署长);
}
常量useStore=()=>{
const[logs,setLogs]=useState([])
useffect(()=>{
AsyncStorage.getItem(“日志”)。然后((newLogs)=>setLogs(newLogs));
}, [])
useEffectIgnoringFirstChange(()=>{
//不希望在初始加载时或刚加载'logs'时设置项。
AsyncStorage.setItem(“logs”,JSON.stringify(logs));
},[日志])
常量addLog=(新文本)=>{
设置日志(日志=>[
{text:newText,createdAt:new Date().getTime()},
…日志,
]);
}
返回{
日志,
addLog,
//…许多其他更新日志的功能
}
}

这就是我最终得到的,我仍然想知道这是否是最好的解决方案,因此欢迎使用更优雅的解决方案:

const AsyncStorage = require("@react-native-community/async-storage")

const useStore = () => {
  const justLoaded = useRef(true);
  const [logs, setLogs] = useState([])

  useEffect(() => {
    AsyncStorage.getItem("logs").then((newLogs) => {
     justLoaded.current = true;
     setLogs(newLogs));
    }
  }, [])

  useEffect(() => {
    //Don't want to setItem on initial load or when `logs` was just loaded.
    if (justLoaded.current === false) AsyncStorage.setItem("logs", JSON.stringify(logs));
    if (justLoaded.current) justLoaded.current = false;
  }, [logs])

  const addLog = (newText) => {
    setLogs(logs => [
      {text: newText, createdAt: new Date().getTime()},
      ...logs,
    ]);
  }

  return {
    logs,
    addLog,
    //...many other functions that update logs
  }
}

我认为包装setstate方法是一种更干净的方法,可以控制何时应该发生日志持久化。大概是这样的:

const AsyncStorage = require("@react-native-community/async-storage")

const useStore = () => {
  const [logs, setLogsState] = useState([])
  const persistLogsRef = useRef(false)

  const setLogs = (updatedLogs) => {
    persistLogsRef.current = true
    setLogsState(updatedLogs)
  }

  useEffect(() => {
    AsyncStorage.getItem("logs").then((newLogs) => setLogsState(newLogs));
  }, [])

  useEffect(() => {
    //Don't want to setItem on initial load or when `logs` was just loaded.
    if (persistLogsRef.current) {
      AsyncStorage.setItem("logs", JSON.stringify(logs));
    }
  }, [logs])

  const addLog = (newText) => {
    setLogs(logs => [
      {text: newText, createdAt: new Date().getTime()},
      ...logs,
    ]);
  }

  return {
    logs,
    addLog,
    //...many other functions that update logs
  }
}

因此,本质上,您希望将其用作
componentdiddupdate
hook?您可以编写一个忽略第一个更改的hook。?这仍然会调用
AsyncStorage.setItem(“logs”,JSON.stringify(logs))在第一次useEffect设置日志后。您可以使用ref检查更新。我已经更新了上面的代码。我不愿意将
allowSettingLogs.current=true
添加到我所有更新
logs
的函数中,尽管有addLog、deleteLog、updateLog。。。。有没有办法只在
AsyncStorage.getItem
行中添加标记?对于刚从AsyncStorage检索到的日志,它仍将调用一次。可以修改为使用计数。我认为这是一个关于如何传播数据的更大问题的迹象。你有没有考虑过使用redux?