I'm trying to use localForage in a reactjs app. Calling setItem and then getItem works exactly once. The value that was set with setItem is correctly recovered by getItem. If they are called again after that, a TypeError is thrown:
TypeError: self is undefined localforage.js:1012
The error can be reproduced with a minimal reactjs app, here's just a single functional component.
When the component is rendered, it calls setItem and getItem.
It rerenders on a button click and calls setItem and getItem again. This causes the TypeError.
import React, { useState } from "react";
import { getItem, setItem } from "localforage";
function App() {
const [state, setState] = useState(0);
setItem("test", state).then(() => {
console.log("used localForage");
});
getItem("test").then((val) => {
console.log("got: ", val);
});
return (
<button
onClick={() => {
setState(Math.floor(Math.random() * 10));
}}
>
{state}
</button>
);
}
export default App;
Here is an online version on codesandbox.
Somehow it loses the context internally when importing methods separately, works fine when importing localforage as a whole
import React, { useState } from "react";
import localforage from "localforage";
function App() {
const [state, setState] = useState(0);
localforage.setItem("test", state).then(() => {
console.log("used localForage");
});
localforage.getItem("test").then(val => {
console.log("got: ", val);
});
return (
<button
onClick={() => {
setState(Math.floor(Math.random() * 10));
}}
>
{state}
</button>
);
}
export default App;
Related
How can i update a function from a child using context??
The context
import React from 'react';
const Fin_states = React.createContext({
title: "title_title"
});
export default Fin_states;
This is the main page , the aim is update function_() using set_function_(see the states const [function_,set_function_] ) , but doing it using the context in the List_of_list child.
import React , { useState ,useContext} from 'react';
import Input_list_panel from './Input_list_panel'
import Fin_states from './Financial_instrument_states'
export default function FinancialInstruments() {
//Attribs
const context = useContext(Fin_states);
const [value, set_value] = useState({title:"initial_title"})
const [function_, set_function_] = useState(() => (data) => console.log(data))
// set_function_ is going to be represented by update_function in the context provider.
return (
<>
<Fin_states.Provider value={{ data:value, update_value:set_value,update_function:set_function_}}>
<Input_list_panel/>
</Fin_states.Provider>
<button onClick={()=>function_("data")}>
Add item in child from parent
</button>
</>
);
}
This is the file where the function is going to be modified using useEffect in this line context.update_function(()=>updated_function)
import React , { useState , useEffect, forwardRef ,useRef,useImperativeHandle, useContext } from 'react';
import Fin_states from './Financial_instrument_states'
export default function List_of_list(props) {
const [list_of_list,set_list_of_list]= useState(["data_1","data_2"]);
const context = useContext(Fin_states);
const updated_function=(data)=>{
var new_item=[...list_of_list];
new_item.push(data)
set_list_of_list(new_item);
console.log(list_of_list)
}
useEffect(() => {
/*update_function represents at set_function_ to modify function_() state , see the context
provider in the parent FinancialInstruments*/
context.update_function(()=>updated_function)
}, [])
return (
<>
<Fin_states.Consumer>
{
(context)=>{
return(
<>
<button onClick={
()=>{
updated_function("data")
}
}>
Add item in child
</button>
</>
)
}
}
</Fin_states.Consumer>
</>
);
}
The problem is that when the state of function_() is updated in the main page (FinancialInstruments functional component) it does not use the same context than updated_function() in List_of_list.
How can i have the same result that i have in List_of_list using updated_function() but using function_() in FinancialInstruments?
I have an issue when i try to use functions from a context inside a child component in a React native android app.
Below is my code for the context, and the form component im using it in (stripped down for brevity).
The "isFormOpen" object can be read no problem from inside any children that is wrapped in the provider, but when i try to call the "toggleForm" function from the same child component, it does nothing, no console errors either.
I have another context which is identical in structure and syntax except for vairable and function names etc, and that works perfectly, so im a bit confused as to why this does not work. I removed the other context, thinking there might be some type of conflict, but didnt solve it.
AccountContext.tsx
import React, { FC, createContext, useContext, useState } from 'react';
interface AccountContextType {
isFormOpen: boolean,
toggleForm: (toggle: boolean) => void
};
export const AccountContext = createContext<AccountContextType>({
isFormOpen: false,
toggleForm: () => null
});
export const AccountContextProvider: FC = props => {
const [formOpen, setFormOpen] = useState<boolean>(false);
const toggleForm = (toggle: boolean) => {
setFormOpen(toggle);
}
const value: AccountContextType = {
isFormOpen: formOpen,
toggleForm
}
return (
<AccountContext.Provider value={value}>
{props.children}
</AccountContext.Provider>
)
}
export const useAccountContext = () => useContext(AccountContext);
TrackUploadForm.js
import React from 'react';
import { SafeAreaView } from 'react-native';
import { Button } from 'react-native-paper';
import { useAccountContext } from '../contexts/AccountContext';
import { AccountContextProvider } from '../contexts/AccountContext';
const TrackUploadForm = () => {
const accountContext = useAccountContext();
return (
<AccountContextProvider>
<SafeAreaView>
<Button onPress={() => accountContext.toggleForm(false)} mode='outlined'>Cancel</Button>
</SafeAreaView>
</AccountContextProvider>
)
};
export default TrackUploadForm;
useAccountContext is called outside the provider
export default function App() {
return (
<AccountContextProvider>
<Content />
</AccountContextProvider>
);
}
const Content = () => {
const accountContext = useAccountContext();
return (
<div className="App">
<h1>{accountContext.isFormOpen ? "true" : "false"}</h1>
<Button onPress={() => accountContext.toggleForm(false)} mode='outlined'>Cancel</Button>
</div>
);
};
accountContext.toggleForm(false) <-- always false, change it to accountContext.toggleForm(!accountContext.isFormOpen)
Together we have
https://codesandbox.io/s/cranky-panini-yo129
I try to set state , but I got error "Hooks can only be called inside of the body of a function component."
This is the code import React, { useState } from "react";
import AuthService from "../Services/AuthService";
const [Searchfile, setSearchfile] = useState([]);
AuthService.getalldata().then((res) => {
setSearchfile(res.data);
});
// const Searchfile = [
// { title: "ayam", singer: "gigi" },
// { title: "ucuk", singer: "asd" },
// ];
export default Searchfile;
Can someone explain to me why that is error and how to fix it ? :D
try adding a functional component and paste the code there.
import React, { useState } from 'react';
function Example() {
const [count, setCount] = useState(0);
return (
<div>
<p> {count}</p>
<button onClick={() => setCount(count + 1)}>
click here
</button>
</div>
);
}
You are breaking the rules of hooks by attempting to call the useState hook outside of a functional component. After looking over your code, it seems like you want to create a custom hook of some sort so my suggestion would be todo something like this:
import { useState } from 'react'
import AuthService from "../Services/AuthService";
const UseSearchFile = () => {
const [Searchfile, setSearchfile] = useState([]);
AuthService.getalldata().then((res) => {
setSearchfile(res.data);
});
return {Searchfile}
}
export default UseSearchFile
you would then import it where you need it like so:
import UseSearchFile from ...correct path
and call it like so:
const { Searchfile } = UseSearchFile()
I have a problem with hooks in ReactJS
as you see here i defined a prop that should call from child component
but when i want to change the value by calling change component it doesn't work and my state doesn't set.
can someone help me?
don't forget to read the comments
import React, {useState} from "react";
import Collection from "./Collection";
import ReminderPeriod from "./ReminderPeriod";
function SingleReminderPage() {
const [collection, setCollection] = useState(null);
const setSelectedCollection = (e) => {
setCollection(e);
console.log(e); // returns the true value
console.log(collection); // returns null
}
return(
<div>
<Collection onChoosed={(e) => setSelectedCollection(e)}/>
</div>
)
}
export default SingleReminderPage;
Use setState with a callback function
const setSelectedCollection = (e) => {
setCollection((state)=> {...state, e});
}
setCollection(e) - wont update the state immediately.
I want to Understand SetState and Prevstate in ReactJS
This might help you around, the useEffect will be called on each colletion update
import React, { useState, useEffect } from "react";
import Collection from "./Collection";
import ReminderPeriod from "./ReminderPeriod";
function SingleReminderPage() {
const [collection, setCollection] = useState(null);
useEffect(() => {
console.log(collection)
}, [collection])
return (
<div>
<Collection onChoosed={(e) => setCollection(e)} />
</div>
)
}
export default SingleReminderPage;
it seems like the setCollection is called after the logging action to check something like that you can print the collection value on the component itself
import React, {useState} from "react";
import Collection from "./Collection";
import ReminderPeriod from "./ReminderPeriod";
function SingleReminderPage() {
const [collection, setCollection] = useState(null);
const setSelectedCollection = (e) => {
setCollection(e);
console.log(e); // returns the true value
console.log(collection); // returns null
}
return(
<div>
{collection}
<Collection onChoosed={(e) => setSelectedCollection(e)}/>
</div>
)
}
export default SingleReminderPage;
It's really basic I guess. I'm trying to add onClick callback to my script & I believe I'm missing a value that would be responsible for finding the actual item.
Main script
import React from 'react';
import { CSVLink } from 'react-csv';
import { data } from 'constants/data';
import GetAppIcon from '#material-ui/icons/GetApp';
import PropTypes from 'prop-types';
const handleClick = (callback) => {
callback(callback);
};
const DownloadData = (props) => {
const { callback } = props;
return (
<>
<CSVLink
data={data}
onClick={() => handleClick(callback)}
>
<GetAppIcon />
</CSVLink>
</>
);
};
DownloadData.propTypes = {
callback: PropTypes.func.isRequired,
};
export default DownloadData;
Storybook code
import React from 'react';
import DownloadData from 'common/components/DownloadData';
import { data } from 'constants/data';
import { action } from '#storybook/addon-actions';
export default {
title: 'DownloadData',
component: DownloadData,
};
export const download = () => (
<DownloadData
data={data}
callback={action('icon-clicked')}
/>
);
So right now with this code on click in the storybook I'd get null and I'm looking for an object.
One of the potential issues I can see is that your handleClick function is stored as it is in-memory, when you import the component. That means you're keeping reference of something that doesn't exists and expects to use it when rendering the component with the callback prop.
Each instance of a component should have its own function. To fix it, move the function declaration inside the component. Like this:
const Foo = ({ callback }) => {
// handleClick needs to be inside here
const handleClick = callback => {
console.log("clicked");
callback(callback);
};
return <div onClick={() => handleClick(callback)}>Click me!</div>;
};
Check this example.
If this doesn't fix your problem, then there is something wrong with how you're implementing Storybook. Like a missing context.