You won't be able to get access to this data in a React-type way, however you can get access to this data using plain JavaScript, which React supports. Basically you can't treat these inputs as controlled components, instead as uncontrolled components.
This means however that you won't get state updates in real time like you do with controlled components, but you can still get access to the data. You'll just have to get the data from the DOM when you need it (e.g. upon submission).
Since you also won't be able to pass refs directly to these components, you'll have to query the DOM. You can start with a ref for your container (the one whose inner HTML gets dangerously set) and then query for input
elements (and/or the other input-like elements).
Here's an example:
App.js
export default function App() {
const dataContainerRef = React.useRef(null);
const handleSubmission = e => {
e.preventDefault();
const inputs = Array.from(dataContainerRef.current.querySelectorAll("input"));
// if your inputs have unique names:
const formData = Object.fromEntries(inputs.map(input => [input.name, input.value]));
// or just get an array of the values:
const formDataArray = inputs.map(input => input.value);
};
return (
<div className="App">
<Inner dataContainerRef={ dataContainerRef } />
<form onSubmit={handleSubmission}>
<div>Both two values comma separated: </div>
<button type="submit"> Submit </button>
</form>
</div>
);
}
Inner.js
export default function Inner(props) {
const { dataContainerRef } = props;
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<div
ref={dataContainerRef}
className="data-container"
dangerouslySetInnerHTML={{ __html: data.htmltag }}
/>
</div>
);
}
Here's a codesandbox demo.
Note that you can look into this question about getting form data with JS if you want to know about other ways you can get the form data using plain JS (I'd recommend not importing jQuery into your React project).
Alternate Approach
If you're open to changing the structure of your data so that that data
is not an HTML string and instead is in JSON format, you can dynamically create the input
elements yourself and control them like normal.
For example, if you structure data
like this:
const data = {
inputNames: ["Hello", "Welcome"],
}
Then you can create formData
of the form:
{
Hello: "",
Welcome: "",
}
which should be stored in the parent of Inner
because it owns the submission function.
Then you'll just need to initialize the formData
from data
and then dynamically create an input
element for each inputName
given.
Here's a sample of Inner
:
export default function Inner(props) {
const { formData, setFormData } = props;
React.useEffect(() => {
// initialize `formData`
setFormData(
Object.fromEntries(data.inputNames.map(inputName => [inputName, ""]))
);
}, [setFormData]);
const inputRows = data.inputNames.map(inputName => (
<tr key={inputName}>
<td>{inputName}</td>
<td>
<input
name={inputName}
value={formData[inputName]}
onChange={event => {
event.persist();
setFormData(prev => ({
...prev,
[event.target.name]: event.target.value
}));
}}
/>
</td>
</tr>
));
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<table>
<tbody>{inputRows}</tbody>
</table>
</div>
);
}
Here's a demo.