I appear to be going around in circles on this one.
I have created an Edit Form that is featured within a modal. This is accessed via a button that sits on a display page. The contents of the display page is dictated by a user menu. The display page component passes the object being displayed to the Edit model to be edited.
Please note that I am yet to tie the app into the backend so the form submission handle lacks any PUT call or error handling. Instead I am emulating this via a console.log.
I have included a portion of my Edit Form code as there are many fields.
import {react,useState,useEffect} from 'react'
import './EditPreGameModel.css'
import DropSearch from './DropSearch/DropSearch'
export default function EditPreGameModal( { open, onClose, preGameTrade} ) {
const [PreGame, setPreGame] = useState(preGameTrade)
const handleChange=(e)=> {
setPreGame({...PreGame,[e.target.name]:e.target.value})
}
const submitHandler=(e)=>{
e.preventDefault();
console.log(PreGame)
onClose()
}
if(!open) return null
return (
<div className='Overlay_style'></div>
<div className='EditPreGameModalCont'>
<div className='EditPreGameHeaders'>
<header className='PreGameName'>{preGameTrade.Tradename}</header>
<header className='editHeader'>PreGame Edit</header>
</div>
<form className='preGameForm' onSubmit={(e)=>submitHandler(e)}>
<div className='FirstEditItems'>
<label>Status:</label>
<select className="editDropdown" name="Status" value={PreGame.Status} onChange={(e)=>handleChange(e)}>
<option className="DropOptions" value="PreGame">PreGame</option>
<option className="DropOptions" value="InGame">InGame</option>
</select>
<label>Instrument:</label>
<select className="editDropdown" name="Instrument" value={PreGame.Instrument} onChange={(e)=>handleChange(e)}>
<option className="DropOptions" value="FX">FX</option>
<option className="DropOptions" value="Crypto">Crypto</option>
<option className="DropOptions" value="Equities">Equities</option>
</select>
<label>Ticker:</label>
<DropSearch ticker={PreGame.Instrument="FX"? PreGame.FXSymbol : PreGame.Instrument="Crypto"? PreGame.Crypto : PreGame.StockSymbol}></DropSearch>
</div>
<div className='SecondEditItems'>
<label>Category:</label>
<select className="editDropdown" name="BuySell" value={PreGame.BuySell} onChange={(e)=>handleChange(e)}>
<option className="DropOptions" value="Buy">Buy</option>
<option className="DropOptions" value="Sell">Sell</option>
</select>
</div>
<div className='EditControl'>
<button type='submit' className='EditControlButton'>Submit</button>
<button className='EditControlButton' onClick={onClose}>Exit</button>
</div>
</form>
</div>
)
}
The challenge I am facing is begins with the copy I am making via:
const [PreGame, setPreGame] = useState(preGameTrade)
This receives the object to be edited and creates a copy to be edited by the user prior to being submitted. This is done to stop edits occurring directly on the original. The logic here was that I didn't want edits to be passed back up to display page without a submission. This stops edits showing even when the user cancels the edit halfway through. The ambition was to have the user build the copy PreGame and commit that to a PUT request. The display component would then request a refresh of the data and present it back to the User.
However, this results in another issue. Selecting and Editing the first item seems fine but if the user navigates the menu, selects another object and clicks Edit, the object held within PreGame remains to be the original rather than the new. The fields remain tied to the original.
One final note - the Edit Form header is the name of the object and this isn't intended to be editable in this version. As a result I just call the name of the original object. This changes fine whilst navigating through different objects.
Am I approaching this incorrectly? Do I need a useEffect() ref to listen for changes in preGameTrade and then call the setPreGame()?
Thanks, any help is great appreciated.
CodePudding user response:
To address the issue wherein your edit-form is not being sensitive to user selection.
you can add a useEffect block sensitive to preGameTrade prop
const [PreGame, setPreGame] = useState(preGameTrade)
useEffect(() => {
setPreGame(preGameTrade);
}, [preGameTrade]);
Explanation:
the state variable will not get updated on changing the props passed to the component by itself. To do this we need a useEffect block.
CodePudding user response:
You need to update the object that's passed into props. If you want to edit the now modified instance again, you'll need to call a function that's passed into the editing component. We can call it the "update function".
That update function can be called, in your case, inside the submitHandler
function - after the success of the PUT request. The update function is called in the child component, but it's execution happens on the parent.
This is called "lifting state". Here's some snippets that I think capture the idea.
// The child component
const Child = (preGame, updatePregame) => {
const submitHandler=(e)=>{
e.preventDefault();
console.log(PreGame)
updatePregame(PreGame)
onClose()
}
};
// The parent component
const Parent = () => {
const updatePreGame = (pregame) => {
// Update the instance of pregame with the values
// from the copy modified in Child.
};
return (
<Child preGame={pregame} updatePregame={updatePregame} />
);
}
CodePudding user response:
The issue is in the way you are adding properties to the object
setPreGame({...PreGame,`${e.target.name}`:e.target.value})
} ```