我似乎无法使以下代码正常工作。尝试在响应中使用一些简单的“缓存”,我希望使用上下文将其从App组件中传递出去。 App中的状态如下:
const [cacheData, setCacheData] = useState({});
const getCache = (key) => {
console.log('Getting value from cache with key ' + key, cacheData);
return cacheData[key];
}
const setCache = (key, data) => {
try{
console.log(cacheData);
console.log('Setting value to cache with key ' + key, data);
let dataCopy = JSON.parse(JSON.stringify(cacheData));
dataCopy[key] = data;
console.log(dataCopy, cacheData);
setCacheData(dataCopy);
console.log('jaja');
}catch(err){
console.log(err);
}
}
然后将其传递给上下文,如下所示:
<CacheContext.Provider value={{data: cacheData, get: getCache, set: setCache}}>
在子组件中,我使用cache.get和cache.set,它们都具有正确的console.logs,但是缓存始终是未定义的。缓存数据始终为{}
。我的猜测是setCache函数没有做任何事情。
先谢谢大家。另外,如果您认为我正在重新发明轮子,请给我一些帮助:)找不到任何可以帮助我的软件包。
代码段:(从答案中复制,此代码有效。将添加错误代码)
const {useState, useContext, createContext} = React
const fn = () => undefined
const CacheContext = createContext({data: {}, get: fn, set: fn})
const App = () => {
const [cacheData, setCacheData] = useState({});
const getCache = (key) => {
console.log('Getting value from cache with key ' + key, cacheData);
return cacheData[key];
}
const setCache = (key, data) => {
try{
console.log(cacheData);
console.log('Setting value to cache with key ' + key, data);
let dataCopy = JSON.parse(JSON.stringify(cacheData));
dataCopy[key] = data;
console.log(dataCopy, cacheData);
setCacheData(dataCopy);
console.log('jaja');
}catch(err){
console.log(err);
}
}
return (
<CacheContext.Provider value={{data: cacheData, get: getCache, set: setCache}}>
<Main />
</CacheContext.Provider>
)
}
const useCache = () => useContext(CacheContext)
const Main = () => {
const cache = useCache()
const [key, setKey] = useState('key')
const [value, setValue] = useState('value')
return (
<div>
<input value={key} onChange={(e) => setKey(e.target.value)} /> :
<input value={value} onChange={(e) => setValue(e.target.value)} />
<button onClick={() => cache.set(key, value)}>Set</button>
<div>Existing keys: [{Object.keys(cache.data).join(', ')}]</div>
<div>Current value of '{key}': {cache.get(key) || 'undefined'}</div>
</div>
)
}
ReactDOM.render(<App />, document.getElementById('root'))
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>
答案 0 :(得分:0)
为什么不使用LocalStorage或SessionStorage(特定于选项卡)?只需从localStorage推送并获取,您就可以成为好人。或者使用redux-store和redux-persist来处理刷新。
redux:https://www.npmjs.com/package/react-redux
redux-persist:用于将redux存储的数据存储到localStorage的插件:https://www.npmjs.com/package/redux-persist
答案 1 :(得分:0)
问题中的代码按以下方式使用时效果很好。请通过在问题中包括以下代码段并对其进行编辑,直到重现问题,create a Minimal, Reproducible Example {3>}:
const {useState, useContext, createContext} = React
const fn = () => undefined
const CacheContext = createContext({data: {}, get: fn, set: fn})
const App = () => {
const [cacheData, setCacheData] = useState({});
const getCache = (key) => {
console.log('Getting value from cache with key ' + key, cacheData);
return cacheData[key];
}
const setCache = (key, data) => {
try{
console.log(cacheData);
console.log('Setting value to cache with key ' + key, data);
let dataCopy = JSON.parse(JSON.stringify(cacheData));
dataCopy[key] = data;
console.log(dataCopy, cacheData);
setCacheData(dataCopy);
console.log('jaja');
}catch(err){
console.log(err);
}
}
return (
<CacheContext.Provider value={{data: cacheData, get: getCache, set: setCache}}>
<Main />
</CacheContext.Provider>
)
}
const Main = () => {
const {data, get, set} = useContext(CacheContext)
const [key, setKey] = useState('key')
const [value, setValue] = useState('value')
return (
<div>
<input value={key} onChange={(e) => setKey(e.target.value)} />
:
<input value={value} onChange={(e) => setValue(e.target.value)} />
<button onClick={() => set(key, value)}>Set</button>
<div>Existing keys: [{Object.keys(data).join(', ')}]</div>
<div>Current value of '{key}': {get(key) || 'undefined'}</div>
</div>
)
}
ReactDOM.render(<App />, document.getElementById('root'))
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>
话虽如此,functional updates可以在the new state is computed using the previous state
时使用。而且,如果您发现需要命令性代码,异步操作,使用闭包和/或针对性能进行优化的代码的可变引用,则可以使用useRef访问data
的未来值:
const {useState, useContext, useRef, createContext, memo} = React
const fn = () => undefined
const CacheContext = createContext({data: {}, get: fn, set: fn})
const App = memo(() => {
const [cacheData, setCacheData] = useState({});
const dataRef = useRef();
dataRef.current = cacheData;
const getCache = (key) => {
console.log('Getting value from cache with key ' + key, cacheData);
return cacheData[key];
}
const setCache = (key, data) => {
try{
console.log(cacheData);
console.log('Setting value to cache with key ' + key, data);
setCacheData(current => {
const dataCopy = JSON.parse(JSON.stringify(current));
dataCopy[key] = data;
return dataCopy;
})
setCacheData(dataCopy);
console.log('jaja');
}catch(err){
console.log(err);
}
}
return (
<CacheContext.Provider value={{dataRef, get: getCache, set: setCache}}>
<Main />
</CacheContext.Provider>
)
})
const Main = memo(() => {
const {dataRef, get, set} = useContext(CacheContext)
const [key, setKey] = useState('key')
const [value, setValue] = useState('value')
const setAsync = () => {
set('in progress', key)
setTimeout(() => {
set(key, value)
// notice how mutating a reference will NOT trigger a re-render, unlike using `set`
// set('in progress', undefined)
delete dataRef.current['in progress']
}, 3000)
}
return (
<div>
<input value={key} onChange={(e) => setKey(e.target.value)} />
:
<input value={value} onChange={(e) => setValue(e.target.value)} />
<button onClick={setAsync}>Set</button>
<div>Existing keys: [{Object.keys(dataRef.current).join(', ')}]</div>
<div>Current value of '{key}': {get(key) || 'undefined'}</div>
<div>Current value of 'in progress': {get('in progress') || 'undefined'}</div>
</div>
)
})
ReactDOM.render(<App />, document.getElementById('root'))
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>