Reputation: 1080
I'm a beginner React developer and I'm having an issue with this particular code snippet.
Issues:
I purposely chose to use useRef instead of useState because after the user adds or edit whatever links they want, I want to send keyRef to a NoSQL database; whereas when I used useState() it was giving me stale state issues, where the array with all the links were not updated constantly.
Any suggestions? Please and thank you!
CodeSandbox link: https://codesandbox.io/s/react-hooks-counter-demo-forked-0bjdy?file=/src/index.js
App.js
import React, { useState, useRef } from "react";
import ReactDOM from "react-dom";
import { links } from './links';
import "./styles.css";
function App() {
const [loaded, setLoaded] = useState(false);
const formRef = useRef([]);
const keyRef = useRef([]);
if (!loaded) {
keyRef.current = links;
links.forEach(link => RenderLinks(link.id));
setLoaded(true);
}
function RenderLinks(id) {
const formLength = formRef.current.length;
if (id === null)
formRef.current = [ ...formRef.current, <AddLink key={formLength} id={formLength} /> ];
if (id && !formRef.current.find(form => form.props.id === id))
formRef.current = [ ...formRef.current, <AddLink key={formLength} id={formLength} /> ];
}
function AddLink(props) {
const id = props.id;
const value = keyRef.current[id] ? keyRef.current[id].link : '';
const [input, setInput] = useState(value);
keyRef.current = [
...keyRef.current,
{
id: id,
link: '',
}
];
return <input onChange={e => setInput(e.target.value)} value={input} />
}
return (
<div>
<button onClick={() => RenderLinks(null)}>add</button>
{formRef.current ? formRef.current.map(child => child) : null}
</div>
)
}
links.js aka dummy data
export const links = [
{
id: 0,
link: "www.zero.com"
},
{
id: 1,
link: "www.one.com"
},
{
id: 2,
link: "www.two.com"
},
{
id: 3,
link: "www.three.com"
},
{
id: 4,
link: "www.four.com"
},
{
id: 5,
link: "www.five.com"
},
{
id: 6,
link: "www.six.com"
},
{
id: 7,
link: "www.seven.com"
}
];
Upvotes: 19
Views: 43945
Reputation: 169
You have to use both useState
and useRef
.
useRef
for keeping the latest value and useState
for updating the state.
Example :
const showARef = useRef("inline");
const showBRef = useRef("inline");
const [showA, setshowA] = useState(showARef.current);
const [showB, setshowB] = useState(showBRef.current);
Upvotes: 6
Reputation: 101
You can use a state variable to re render all state components, a simple one which I have tried and have succeeded in doing is :
const [, forceUpdate] = useReducer((x) => x + 1, 0)
You can call forceUpdate() when you have added your links and it will function as useState()
Upvotes: 9
Reputation: 6482
From the React useRef() docs:
Keep in mind that useRef doesn’t notify you when its content changes. Mutating the .current property doesn’t cause a re-render
So even though it is being updated, you will never get a re-render showing the 7th, 8th, etc. links that have been added.
I think you would be better off using useState()
hook for your links and rendering those. Perhaps a separate question can identify the stale issues you were seeing.
Upvotes: 18