This is the most frequent problem I come across, in this file was trying to access the innerHTML of the textarea using the same property.
But the error says that the input.innerHTML is null.
You can understand better by code,
import React, { Component, useEffect, useState } from 'react'
import './Body.css';
import axios from "axios";
import './Body.css'
export default function Navbar() {
let noteArray;
let input = document.getElementById('.input_area') ;
const AddNote = () =>{
console.log("here" ,input.innerHTML) ;
}
return (
<>
<div>
<div className="input_info">
<textarea id='input_area' name="" cols="50" rows="5">op</textarea>
<br />
<button onClick={AddNote} className='add'>Add Note</button>
</div>
<br />
<div id='display_info' >
</div>
</div>
</>
)
}
I tried from class, id, and querySelector but none of them is working.
Can anyone suggest me some edits?
EDIT--
CodePudding user response:
To be sure that the elements of the component has been mounted to the DOM
you need to execute the selection queries in useEffect
hook, Also you need to use value
attribute instead of innerHTML
import React, { Component, useEffect, useState } from 'react'
import './Body.css';
import axios from "axios";
import './Body.css'
export default function Navbar() {
let noteArray;
useEffect(() => {
let input = document.getElementById('.input_area');
console.log("here" ,input.value);
})
const AddNote = () =>{
let input = document.getElementById('.input_area');
console.log("here" ,input.value);
}
return (
<>
<div>
<div className="input_info">
<textarea id='input_area' name="" cols="50" rows="5">op</textarea>
<br />
<button onClick={AddNote} className='add'>Add Note</button>
</div>
<br />
<div id='display_info' >
</div>
</div>
</>
)
}
But, I suggest you use useRef
instead of DOM
select queries.
For example
import React, { Component, useEffect, useState, useRef } from 'react'
import './Body.css';
import axios from "axios";
import './Body.css'
export default function Navbar() {
let noteArray;
const textAreaRef = useRef(null)
useEffect(() => {
console.log(textAreaRef.current.value)
})
const AddNote = () =>{
console.log(textAreaRef.current.value)
}
return (
<>
<div>
<div className="input_info">
<textarea ref={textAreaRef} id='input_area' name="" cols="50" rows="5">op</textarea>
<br />
<button onClick={AddNote} className='add'>Add Note</button>
</div>
<br />
<div id='display_info' >
</div>
</div>
</>
)
}
CodePudding user response:
const { useState } = React;
function Navbar() {
const [input, setInput] = useState("op");
const [noteArray, setNoteArray] = useState([])
const addNote = () => {
setNoteArray((prevState) => ([...prevState, input]))
}
const inputChange = (e) => {
setInput(e.target.value)
}
return (
<div>
<div className="input_info">
<textarea id='input_area' name="" cols="50" rows="5" value={input} onChange={e => inputChange(e)}></textarea>
<br />
<button className='add' onClick={addNote}>Add Note</button>
</div>
<br />
<div id='display_info' >
<ul>
{noteArray.map(val => {
return <li>{val}</li>
})
}
</ul>
</div>
</div>
);
}
ReactDOM.render(<Navbar />, document.getElementById("root"))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>
<body id="root"></body>
I guess this is what you want to achieve and a better pattern in react. Also you can improve it by changing the data structure of note array