Im not sure why but it seems that my axios function is running twice is there any way I could circumvent this? I have a couple useState methods above but I am still confused why it is basically running everything twice
here is the code that is running twice in react
function App() {
let num = [];
num[0] = 0;
if (localStorage.getItem("winstreak") === null) {
localStorage.setItem("winstreak", JSON.stringify(num));
} else {
}
let winstreak = JSON.parse(localStorage.getItem("winstreak"));
let array = JSON.stringify(localStorage.getItem("winstreak"));
let streaks = winstreak.reduce(
function (res, n) {
if (n) res[res.length - 1]++;
else res.push(0);
return res;
},
[1]
);
let streak = Math.max.apply(Math, streaks);
var current = localStorage.getItem("gamesplayed", 0);
var correct = localStorage.getItem("correctgames", 0);
localStorage.getItem("winstreak", winstreak);
const [victory, setVictory] = useState("");
const [seconds, setseconds] = useState();
const [minutes, setminutes] = useState();
const [hours, sethours] = useState("");
const [useHint, setHint] = useState(false);
const [gamestatus, setGameStatus] = useState(false);
const [Attempts, SetAttempts] = useState(0);
const [divnum, setDiv] = useState(1);
const [complete, setComplete] = useState(false);
const [isOpen, setIsOpen] = useState(false);
const [buttonpopup, setbuttonpopup] = useState(false);
const [tweets, setTweet] = useState();
const [sharebut, setSharebut] = useState(false);
const [answer, setAnswer] = useState();
const [answer2, setAnswer2] = useState();
getTweet();
function getTweet() {
axios
.get("https://tweetleserver.herokuapp.com/")
.then((res) => {
setTweet(res.data.data.id);
setAnswer(res.data.includes.users[0].name);
setAnswer2(res.data.includes.users[0].username);
console.log("test");
return;
})
.catch((err) => {
console.log(err);
return;
});
}
}
I am calling this function only once but I am still confused as to why it could be doing this
just move the getTweet() inside useEffect will solve the infinit loop (whether you have it) because it's not nice practice if you call it directly in the body of the functional component.
Also i would prefer to have one setState , so one state instead of having multi states .
I mean instead of :
setTweet(res.data.data.id);
setAnswer(res.data.includes.users[0].name);
setAnswer2(res.data.includes.users[0].username);
you can write this :
setSomeState(prevState => ({
...prevState,
tweet: res.data.data.id
answer: res.data.includes.users[0].name,
answer2: res.data.includes.users[0].username
}));
and the state will be :
const [someState, setSomeState] = useState({
tweet: "",
answer: "",
answer2: ""
});
Related
I'm trying to make voiceAudio as a template so I can play multiple audios if I want. But currently I can play only one audio. If I bring two voiceAudio like I did in example below, one of them wouldn't play.
How can I make it work?!
loginPhone.ts
import {voiceAudio} from '../../src/common/utils/voice';
const LoginPhone = () => {
const domNavigate = useDomNavigate();
const {openKioskAlert} = useContext(KioskAlertContext);
const [phoneNumber, setPhoneNumber] = useState([]);
const {playAudio, stopAudio} = voiceAudio('login-phone');
useEffect(() => {
playAudio();
return () => stopAudio();
}, []);
utils>voice.ts
export const voiceAudio = (title: string) => {
const audioFile = new Audio(`/sounds/${title}.mp3`);
const playAudio = () => audioFile.play();
const stopAudio = () => {
audioFile.pause();
audioFile.currentTime = 0;
};
return {
playAudio,
stopAudio,
};
};
what I would like to do : example
import {voiceAudio} from '../../src/common/utils/voice';
const LoginPhone = () => {
const domNavigate = useDomNavigate();
const {openKioskAlert} = useContext(KioskAlertContext);
const [phoneNumber, setPhoneNumber] = useState([]);
// if I bring bring?!two voiceAudio, one of them wouldn't work..
const {playAudio, stopAudio} = voiceAudio('login-phone);
const {playAudio, stopAudio} = voiceAudio('login-pin);
useEffect(() => {
playAudio();
return () => stopAudio();
}, []);
const play =
The problem may be that you are trying to use the same variable names multiple times. Notice how playAudio and stopAudio are being used twice. This is similar to writing const a = 8; const a = 5.
Try using different names for the second voiceAudio like this:
const {playAudio, stopAudio} = voiceAudio('login-phone');
const {playAudio: playAudio2, stopAudio: stopAudio2} = voiceAudio('login-pin');
That will allow you to refer to the playAudio on the second line as playAudio2 and refer to the stopAudio on the second line as stopAudio2.
In your useEffect you should then be able to freely call both functions like this:
useEffect(() => {
playAudio();
playAudio2();
return () => {
stopAudio();
stopAudio2();
}
}, []);
This is the error I get : TypeError: observer.getOptimisticResult is not a function
I'm trying to work with React-Query and Supabase to read data into a React-Table. I've created a useReadData.ts hook as shown below:
export default function useReadData(table_name, startRow, endRow) {
return useQuery(
["read_data"],
() =>
supabase
.from(table_name)
.select("*")
.range(startRow, endRow)
.then(handleSupabaseError)
.then(({ data }) => data)
);
}
I have called this hook in my index.tsx file within the App() component:
function App() {
const [rowData, setRowData] = React.useState([]);
const [loading, setLoading] = React.useState(false);
const [pageCount, setPageCount] = React.useState(0);
const fetchIdRef = React.useRef(0);
const fetchData = React.useCallback(({ pageSize, pageIndex }) => {
if (fetchId === fetchIdRef.current) {
const startRow = pageSize * pageIndex;
const endRow = startRow + pageSize;
const table_name = "company";
const data = () => useReadData(table_name, startRow, endRow);
console.log(data);
setRowData(data);
setPageCount(10);
setLoading(false);
}
}, []);
I've spent weeks, but I'm not able to resolve this error. Please help!
There are two problems with your approach.
You're invoking a hook conditionally inside another hook, which breaks the rules of hooks
You're trying to store a function instead of an array inside setRowData
Here's an alternate approach:
index.ts
interface Range{
startRow: number;
endRow: number;
}
function App() {
const [rowData, setRowData] = React.useState([]);
const [loading, setLoading] = React.useState(false);
const [pageCount, setPageCount] = React.useState(0);
const [range, setRange] = React.useState<Range>()
const fetchIdRef = React.useRef(0);
const fetchData = React.useCallback(({ pageSize, pageIndex }) => {
const startRow = pageSize * pageIndex;
const endRow = startRow + pageSize;
setPageDetails({ startRow, endRow });
}, []);
const { data } = useReadData("company", range?.startRow, range?.endRow, fetchIdRef)
useEffect(() => {
setRowData(data)
setPageCount(10);
setLoading(false);
},[data])
}
useReadData.ts
export default function useReadData(table_name, startRow, endRow, fetchIdRef) {
return useQuery(
["read_data"],
() => {
// I don't know the source of fetchId, maybe you can pass it in the hook too?
if (startRow && endRow && fetchId === fetchIdRef.current)
return supabase
.from(table_name)
.select("*")
.range(startRow, endRow)
.then(handleSupabaseError)
.then(({ data }) => data)
// To avoid returning Promise<void>. You can handle this in the useEffect as well
return Promise.resolve([])
}
);
}
I'm not that familiar with react-query, so let me know if there's a problem in this.
Can someone help me please?
I have the following problem!!
Line 93:6: React Hook useEffect has a missing dependency: 'estado'. Either include it or remove the dependency array react-hooks/exhaustive-deps
const [nome, setNome] = useState("");
const [sobreNome, setSobreNome] = useState("");
const [email, setEmail] = useState("");
const [dataNascimento, setDataNascimento] = useState("");
const [phone, setPhone] = useState("");
const [estado, setEstado] = useState();
const [cidade, setCidade] = useState();
const [lojas, setLojas] = useState();
const [valueEstado, setValueEstado] = useState([]);
const [valueUnidade, setValueUnidade] = useState([]);
const navigate = useNavigate();
useEffect(() => {
let arr = [];
unidades.map((item) => {
if (estado === item.UF) {
arr.push(item.Cidade);
}
return true
});
setValueEstado(arr);
}, [estado]);
useEffect(() => {
let arr = [];
unidades.map((item) => {
if (cidade === item.Cidade && estado === item.UF) {
arr.push({ Loja: item.Loja, CodigoFilial: item.CodigoFilial });
}
return true
});
setValueUnidade(arr);
}, [cidade]);
Your second useEffect accesses the state variable "estado" but you don't list it in the dependency array (the second argument of useEffect). Note, this will cause your second useEffect to rerun anytime "estado" changes.
I am trying to pass some custom metadata to my firebase firestore, I believe I must pass the metadata I grabbed in my component up to the hook but am unsure how to do so,
my component:
const UploadForm = () => {
const [file, setFile] = useState(null);
const [error, setError] = useState(null);
const [metadata, setMetadata] = useState(null);
const types = ['image/png', 'image/jpeg'];
const changeHandler = (e) => {
let selected = e.target.files[0];
if (selected && types.includes(selected.type)) {
setFile(selected);
setError('');
const pieceName = document.getElementById("pieceName").value;
const pieceDescription = document.getElementById("pieceDescription").value;
const newMetadata = {
customMetaData: {
artName: pieceName,
artDescription: pieceDescription
}
};
setMetadata(newMetadata);
...
export default UploadForm;
& my hook:
const useStorage = (file, metadata) => {
const [progress, setProgress] = useState(0);
const [error, setError] = useState(null);
const [url, setUrl] = useState(null);
useEffect(() => {
// references
const storageRef = projectStorage.ref(file.name);
const collectionRef = projectFirestore.collection('images');
storageRef.put(file).on('state_changed', (snap) => {
let percentage = (snap.bytesTransferred / snap.totalBytes) * 100;
setProgress(percentage);
}, (err) => {
setError(err);
}, async () => {
const url = await storageRef.getDownloadURL();
const createdAt = timestamp();
collectionRef.add({ url, createdAt, metadata });
setUrl(url);
});
}, [file, metadata]);
return { progress, url, error };
}
export default useStorage;
I am able to upload to Firebase Storage/firestore no problem but don't know how to feed this extra metadata.
To change the metada just call the updateMetadata on the ref:
const useStorage = (file, metadata) => {
const [progress, setProgress] = useState(0);
const [error, setError] = useState(null);
const [url, setUrl] = useState(null);
useEffect(() => {
// references
const storageRef = projectStorage.ref(file.name);
const collectionRef = projectFirestore.collection('images');
storageRef.put(file).on('state_changed', (snap) => {
let percentage = (snap.bytesTransferred / snap.totalBytes) * 100;
setProgress(percentage);
}, (err) => {
setError(err);
}, async () => {
await storageRef.updateMetadata(metadata)
const url = await storageRef.getDownloadURL();
const createdAt = timestamp();
collectionRef.add({ url, createdAt, metadata });
setUrl(url);
});
}, [file, metadata]);
return { progress, url, error };
}
export default useStorage;
You can read more about it here.
I want to split an array into two arrays.
The problem is main array which I want to split into two is coming from server.And I need to wait until it loads.
Here my code.
This is useSafeFetch custom Hook which is responsible to fetch data (by the way this is working fine just paste here to show you all code)
const useSafeFetch = (url) => {
const [data, setData] = useState([]);
const [customUrl] = useState(url);
const [isLoading, setIsLoading] = useState(false);
const [isError, setIsError] = useState(false);
useEffect(_ => {
let didCancel = false;
const fetchData = async () => {
if(didCancel === false){
setIsError(false);
setIsLoading(true);
}
try {
const result = await axios(customUrl);
if(didCancel === false){
setData(result.data);
}
} catch (error) {
if(didCancel === false){
setIsError(true);
}
}
if(didCancel === false){
setIsLoading(false);
}
};
fetchData();
return () => {
didCancel = true;
};
}, []);
return {
data,
isLoading,
isError,
}
}
I try to write a function which return a two independent array
export default _ => {
const {data,isLoading,isError} = useSafeFetch(`my api`);
useEffect(_ => {
console.log(data); // length 11
const mainA = splitTwoArrays(data);
console.log("progress",mainA.progressHalf); //length 5
console.log("circle", mainA.circleHalf); //length 1
});
const splitTwoArrays = mainArr => {
const half = mainArr.length >>> 1;
let progressHalf = mainArr.splice(0, half);
let circleHalf = mainArr.splice(half, mainArr.length);
console.log(mainArr);
return {
progressHalf,
circleHalf,
}
}
return (
//do something with data
)
}
This is not worked correctly.
As you can see main data length is 11 but function splitTwoArrays split arrays with wrong way. progressHalf length is 5 another circleHalf is 1.But circleHalf need to 6.
Next try:
using useEffect
export default _ => {
const {data,isError,isLoading} = useSafeFetch(`my api`);
const [progressHalf,setProgressHalf] = useState([]);
const [newArr,setNewArr] = useState([]);
const [half,setHalf] = useState(0);
useEffect(_ => {
setHalf(data.length >>> 1);
setNewArr(data);
const partArr = newArr.slice(0, half);
setProgressHalf([...progressHalf, ...partArr]);
})
return (
//do something with data
)
}
This gets into infinity loop when I uncomment this part setProgressHalf([...progressHalf, ...partArr]);.
I try to give useEffect some dependency but unfortunately this also won't work.
I solve this on my own.
const { data } = useSafeFetch("https://jsonplaceholder.typicode.com/users");
const [copiedData, setCopiedData] = useState([]);
const [halfArr, setHalfArr] = useState([]);
const [secHalf, setSecHalf] = useState([]);
const [half, setHalf] = useState(0);
useEffect(
_ => {
setCopiedData([...data]);
setHalf(data.length >>> 1);
setHalfArr([...copiedData.slice(0, half)]);
setSecHalf([...copiedData.slice(half, copiedData.length)]);
},
[data, half]
);
console.log(halfArr);
console.log(secHalf);
And in the end you get two array which created from main data you get from server.
Codesandbox