我有以下代码,如何防止<div style="width: 300px">300px x auto<div class="App">.App</div></div>
<div style="width: 360px">360px x auto<div class="App">.App</div></div>
<div style="width: 400px">400px x auto<div class="App">.App</div></div>
在初始渲染时被调用2次?它被AsyncStorage.setItem
调用,并且由于[]
已更新,因此从AsyncStorage
加载的任何内容。完美的解决方案根本不应该调用logs
,因为setItem
只是从logs
中检索出来的。
AsyncStorage
答案 0 :(得分:1)
我认为包装您的设置状态方法是一种更清洁的方法,可以控制何时应保留日志。像这样:
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
}
}
答案 1 :(得分:0)
您可以使用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
}
}
答案 2 :(得分:0)
您可能想包装useEffect
并使其忽略第一个更改。
const useEffectIgnoringFirstChange = (fn, deps) => {
const firstCallRef = useRef(true);
useEffect(() => {
if (firstCallRef.current) {
firstCallRef.current = false;
return;
};
fn()
}, deps);
}
const useStore = () => {
const [logs, setLogs] = useState([])
useEffect(() => {
AsyncStorage.getItem("logs").then((newLogs) => setLogs(newLogs));
}, [])
useEffectIgnoringFirstChange(() => {
//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
}
}
答案 3 :(得分:0)
这就是我最终得到的结果,我仍然想知道这是否是最好的解决方案,因此欢迎使用更优雅的解决方案:
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
}
}