import React, { createContext, useContext, useState } from "react";
export const ProductSearchTermContext = createContext(["", undefined]);
function ProductSearchTermContextProvider() {
const [searchTerm, setSearchTerm] = useState("");
function SetSearchTerm(term: string) {
setSearchTerm((oldState) => oldState + term);
}
return (
<ProductSearchTermContext.Provider value={[searchTerm, SetSearchTerm]}>
{children}
</ProductSearchTermContext.Provider>
);
}
export default function Input() {
const [searchTerm, setSearchTerm] = useContext(ProductSearchTermContext);
const onChange = (e: any) => {
e.preventDefault();
setSearchTerm!(e.target.value);
};
return <input value={searchTerm} onChange={onChange} />;
}
export default function App() {
return (
<ProductSearchTermContextProvider>
<Input />
</ProductSearchTermContextProvider>
);
}
I have a simple context that passes useState
‘s getter and setter to an input
field to display and set the state’s value.
Unfortunately, the data is duplicating, and when I type “abcd” I get “aabaabcaabaabcd”.
Here is the SandBox link.
The <input>
value is the entire content shown in UI, not just the last stroke key.
Therefore the SetSearchTerm
wrapper function concatenates too much data (oldState + term
, instead of just term
).
No need for that wrapper, directly pass the state setter to your context value:
<ProductSearchTermContext.Provider
value={[searchTerm, setSearchTerm]} // Lower case set, i.e. directly the state setter
>
If you want to keep using the wrapper function, then simply fix its incorrect behavior, i.e. do not concatenate the previous state with the new input value (which already contains the previous content, unless the user deletes it):
function SetSearchTerm(term: string) {
setSearchTerm(term); // Directly use the input value for the new state value, no need to concatenate with previous state
// Other things to do...
}
2
The issue with the SetSearchTerm function in your code is that you’re appending the new term to the previous searchTerm value rather than replacing it.
function SetSearchTerm(term: string) {
setSearchTerm((oldState) => oldState + term);
}
it takes the old state (oldState) and concatenates the new term (term) to it. This causes the search term to duplicate or append on every input change.
To fix the issue, modify the SetSearchTerm function to simply update the state with the new term, rather than concatenating it:
function SetSearchTerm(term: string) {
setSearchTerm(term); // Replace the old term with the new term
}
It will fix your duplication issue.