I got a project where I am splitting the words from different inputfields and push these to a content
array. The array should 'remember' all the words that have been pushed in it. Currently, whenever the user starts typing in a 'new' (and empty) inputfield, the content
array is cleared because the value is empty.
I got a codesandbox setup here.
So lets say the user types lorem ipsum dolar
in the first inputfield and sit amet
in the second inputfield, the content
array should like like this: ['lorem', 'ipsum', 'dolar', 'sit', 'amet']
How can I achieve this result?
Code for reference
import "./styles.css";
import { useState } from "react";
export default function App() {
const [fields, setFields] = useState([
{ id: 1, value: "" },
{ id: 2, value: "" }
]);
const [content, setContent] = useState([]);
const handleOnChange = (e, idx) => {
let newField = [...fields];
newField[idx].value = e.target.value;
setFields(newField);
//How do I push both the values from field 1 AND 2 in the array?
//Currently, when you switch from inputfield, the content array gets reset
let words = e.target.value.split(" ");
setContent(words);
};
return (
<div>
{fields.map((field, idx) => (
<div>
<span>Field {idx}</span>
<input
className="border-2 border-red-500"
type="text"
key={field.id}
value={field.value}
onChange={(e) => handleOnChange(e, idx)}
/>
</div>
))}
<div style={{ marginTop: "20px", backgroundColor: "gray" }}>
{content.map((item, idx) => (
<div key={idx}>{item}</div>
))}
</div>
</div>
);
}
CodePudding user response:
The content
is derived from the fields
state value
properties, and you don't actually need to store it in a state. Compute the content
on each render.
const { useState } = React;
function App() {
const [fields, setFields] = useState([
{ id: 1, value: "" },
{ id: 2, value: "" }
]);
const handleOnChange = (e, idx) => {
setFields(prevFields => {
const newFields = [...fields];
newFields[idx] = {
...newFields[idx],
value: e.target.value
};
return newFields;
});
};
const content = fields.map(o => o.value).join(' ').split(' ');
return (
<div>
{fields.map((field, idx) => (
<div key={field.id}>
<span>Field {idx}</span>
<input
className="border-2 border-red-500"
type="text"
value={field.value}
onChange={(e) => handleOnChange(e, idx)}
/>
</div>
))}
<div style={{ marginTop: "20px", backgroundColor: "gray" }}>
{content.map((item, idx) => (
<div key={idx}>{item}</div>
))}
</div>
</div>
);
}
ReactDOM.render(
<App />,
root
);
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
<div id="root"></div>
CodePudding user response:
This syntax allow to add the element to current existing array:
setMyArray(oldArray => [...oldArray, newElement]);
CodePudding user response:
Two things needs to be changed:
- use
onBlur
to push your words incontent
. - First push previous words then new words.
working example: https://codesandbox.io/s/goofy-colden-8h5v5
import "./styles.css";
import { useState } from "react";
export default function App() {
const [fields, setFields] = useState([
{ id: 1, value: "" },
{ id: 2, value: "" }
]);
const [content, setContent] = useState([]);
const handleOnChange = (e, idx) => {
let newField = [...fields];
newField[idx].value = e.target.value;
setFields(newField);
};
const onBlur = (e, idx)=> {
//How do I push both the values from field 1 AND 2 in the array?
//Currently, when you switch from inputfield, the content array gets reset
let words = fields[idx].value.split(" ");
setContent([...content, ...words]);
}
return (
<div>
{fields.map((field, idx) => (
<div>
<span>Field {idx}</span>
<input
className="border-2 border-red-500"
type="text"
key={field.id}
value={field.value}
onChange={(e) => handleOnChange(e, idx)}
onBlur={(e) => onBlur(e, idx)}
/>
</div>
))}
<div style={{ marginTop: "20px", backgroundColor: "gray" }}>
{content.map((item, idx) => (
<div key={idx}>{item}</div>
))}
</div>
</div>
);
}