React useRef not updating and rendering new values
Solution 1
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.
Solution 2
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);
Solution 3
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()
Related videos on Youtube
Jpark9061
Updated on May 26, 2022Comments
-
Jpark9061 almost 2 years
I'm a beginner React developer and I'm having an issue with this particular code snippet.
Issues:
- Not all of the dummy data is being rendered even though I directly copied its value and rendered it as separate children
- When I click the add button to make a new input form, it doesn't get added to the render.
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" } ];
-
Caleb Taylor over 3 yearswhen you click add, where's the value coming from? I'm not sure because I see 6 inputs
-
Jpark9061 over 3 yearsHey! You're adding another input box. so that would make it 7 inputs. The values of the input box will later be stored in keyRef and to Firebase, which I haven't added in the code snippet.