Reputation: 109
I am working with react app in typescript. From API, I have this input:
a) list of variable names ["name", "surname"]
b) few strings in form of simple html with variables "<p>Hello, how are you {name}?</p>"
c) number of inputs with variables such as {input1: "name"}
everything as a string/JSON
what i need to do is: render simple html (only few tags) received from API but "create" binding between those dynamic inputs and variables in strings
in static world, result would look like:
[name, setName] = useState("")
<p>Hello, how are you {name}?</p>
<input type="text" onChange={e => setName(e.target.value)}/>
However, all of this is dynamic. String "<p>Hello, how are you {name}?</p>"
doesnt get binded to the input on its own.
I tried:
setting variable [vars, setVars] = useState({})
, property for each dynamic variable, with
a) dangerouslySetInnerHTML - renders only html (cannot bind the variable inside to the input)
b) react-html-parser - same as above
c) babel.transform - couldnt make it work as this is done dynamically and in browser, it cannot find the right preset, i couldnt make the mimified babel.js work with typescript How to render a string with JSX in React
do you see some easy way? For example how could i use React.createElement to render html with "live" variable inside, represented as {variableName}? Or maybe something out of the box? giving each elemnt a class and finding the class in DOM and editing the text with input change would be probably very non-optimal?
I hope this could be a better example:
{response:
{
variables: ["name", "name2", "mood"],
texts: [
"<em> Hello! My name is {name}</em>",
"<p> Hi {name} ! I am <strong>{name2}</strong> and I feel {mood} today</p>"
],
inputs: [
{
label: "How do i feel?"
input: {mood}
}
]
}
}
Upvotes: 1
Views: 6426
Reputation: 55792
EDIT:
This should give you a good idea:
https://stackblitz.com/edit/react-ts-cwm9ay?file=DynamicComponent.tsx
EDIT #2:
I'm pretty good with React and interpolation, it's still in progress (specifically the docs, but the readme is complete) but I'm going to shamelessly plug my ReactAST library
EDIT #3 - If you're interested in doing crazy dynamic interpolation, then you might also want to check out a neat dynamic interpolation (and it's reverse) library
Let's assume this:
{
vars: ['name','surname'],
strings: ["<p>Hello, how are you {name}?</p>","<p> It's night to meet you {name} {surname}"],
inputs: {
input1: 'name',
input2: 'surname'
}
}
Create a component (or set of components) that can do this.
I haven't even ran any of this, but here's the idea. I'll put it in a stackblitz in a bit and polish it up to make sure it works:
const MyDynamicComponent = ({vars,strings,inputs}) => {
const [state,setState] = useState(vars.reduce((acc,var) => ({...acc,[var]:undefined}));
return (
<>
<MyDynamicText vars={vars} strings={strings} state={state}/>
<MyDynamicInputs onChange={(name,val) => setState({[name]:val}) state={state} inputs={inputs}/>
</>
)
}
const MyDynamicText = ({vars,strings,state}) => {
return strings.map((s,i) => s.replaceAll(`{${vars[i]}}`,state[vars[i]])
}
const MyDynamicInputs = ({onChange,inputs,state}) => {
return Object.entries(inputs).map(([inputName,varName]) => <input key={inputName} onChange={e => onChange(varName,e.target.value)} value={state[varName]}/>
}
Upvotes: 1