I'm trying to set the data from child component to parent component's state in turn that data will be assigned to input text field. And then I want to automatically click the button to submit the data from input text field to handleBtnSubmit() function.
But when I did this child component is rendering indefinitely. Can someone please help resolving this kind of situation?
Parent
const [responses, setResponses] = useState([]);
const [currentMessage, setCurrentMessage] = useState('');
const submitAction = () => {
setResponses((responses) => [...responses, message]);
handleMessageSubmit(message.text);
setCurrentMessage('');
};
const handleBtnSubmit = () => {
submitAction();
};
<Messages
messages={responses}
parentData={{ currentMessage, setCurrentMessage, btnRef, handleBtnSubmit }}
/>
<div className='typing-area'>
<div className='input-field'>
<input
type='text'
placeholder='Type something here'
required
value={currentMessage}
onChange={handleMessageChange}
onKeyDown={handleSubmit}
/>
</div>
<button onClick={handleBtnSubmit} ref={btnRef}>
<img src={sendButton} alt='Send Button' />
</button>
</div>
Child
const setMessage = (option) => {
parentData.setCurrentMessage(option);
// parentData.btnRef.current.click();
// console.log(parentData.currentMessage);
};
useEffect(() => {
console.log(setCurrentMessage.currentMessage);
// parentData.btnRef.current.click(); //tried this
// parentData.handleBtnSubmit(); //also also tried directly calling handleBtnSubmit();
//both are causing indefinite rerender
}, [parentData.currentMessage]); //tried this too
<li className='option' key={i} onClick={() => setMessage(option)}>
{option}
</li>
First, pass currentMessage as a separate property, instead of passing it within an object. Something like:
<Messages
messages={responses}
currentMessage={currentMessage}
parentData={{ setCurrentMessage, btnRef, handleBtnSubmit }}
/>;
Then try passing the currentMessage prop as a dependency into the useEffect as shown below:
useEffect(() => {
console.log(currentMessage);
setCurrentMessage.btnRef.current.click();
}, [currentMessage]); // child's message state
This way, the useEffect code is called only when the currentMessage changes, and not indefinitely.
Create another state that stores the full value onclick/submit. And use that value as a dependency to the useEffect()
const [messageText, setMessageText] = useState('');
useEffect(() => {
submitBtnRef.current.click();
}, [messageText]);