I am building an address lookup functionality for an app, and my previous 2 questions have thus far, been unable to garner an answer. I am on the last step, and need to figure this out, so I turn to you stack overflow.
I start with an input, a button and a target input:
<input type='text' name='postcode-lookup' onChange={this.postcodeChange} />
<button onClick={this.searchPostcode}>Search</button>
<input type='text' name='target-for-data' />
Easy enough. Now for the functions attached to both of those elements:
postcodeChange = {e} => {
this.setState({'postcode': e.target.value});
}
searchPostcode = () => {
this.setState({'visible': true});
if(this.state.postcode.length . 0){
Axios.get('postcode look up api here')
.then(response => {
this.setState({'response': response.data});
})
}
}
Ok here, we have 3 state items: postcode, which we will set to an empty string '', visible, which is initially set to true, and response, which is an empty array, that we then populate with the response data of address objects.
My next step, was to display those addresses, so inside the render, I set a const that maps over the response array like so:
const result = this.state.response.map((item) => {
if(this.state.visible === true){
return(
<p key={item.id} onClick={addressClick}>{item.address1Field}</p>
)
}else {
}
})
Ok, so when we click the button, it will return a p tag filled with address data from the array. This also has a function, which is where my problem lies.
Inside of this function I set the visible state item to false, so that the addresses disappear. Easy enough.
But how do I then take the address that I clicked on, and populate it into the original input we started with?
I have tried many things, from setting the state in addressClick, targeting the innerHTML, e.target.value, e.target.innerHTML, and so on and so on for hours.
Any takers? Ideas?
Related
I have tried a bunch of approaches but on this, but it's still bugging the hell out of me. I am using React 17.0.1 in this project.
I have a array of objects formatted like so:
gameNumberFields: [{ name: 'gameNum', placeholder: 'GGG', size: '3', value: '', dataindex: '0' }];
For now, there is just one object in the array, but there is always the possibility of more down the road (hence why it's an array).
In the code - this field is pre-populated on initialization - so the "value" of the first index in the array might be something like "123". I use initialState to make this happen:
const [gameNumberFields, setGameNumberFields] = useState(scratchTicketFields?.gameNumberFields ?? []);
When the display is shown to the user - this value is shown to the user in an field using the defaultValue.
return gameNumberFields.map((field, index) => {
const ref = React.createRef();
elemRefs.push(ref);
return (
<div className='d-inline-block ticket-number-inputs' key={`game-numbers--${index}`}>
<input
type='text'
id={field.name}
data-index={field.dataindex}
ref={ref}
className='theme-input'
placeholder={field.placeholder}
size={field.size}
maxLength={field.size}
defaultValue={field.value}
onBlur={(event) => handleGameNumberChange(event, field)}
onKeyUp={(event) => autoTab(event, elemRefs)}
required
/>
<span className='dash'>—</span>
</div>
);
});
}; // end GameIdFieldInputs
So far - so good. The problem I am having is in the onBlur event handler. For some reason - when the user changes the value to something else - it always goes back to the old value.
Here is the handler:
const handleGameNumberChange = async (event, field) => {
// get gameNum from the event target
const gameNum = event.target.value; // say this becomes 999
// do a deep copy of the gameNumberField state.
let gameIdField = JSON.parse(JSON.stringify(gameNumberFields));
// check that we are changing the right index in the array
const fieldIndex = gameIdField.findIndex((obj) => obj.name == field.name);
// make a new object changing the value to 999
let newGameObject = { ...gameIdField[fieldIndex], value: gameNum };
console.log('newGameObject', newGameObject);
//NOTE: At this point the newGameObject is correct and updated with the NEW gameNum of 999
// create a new array and PUSH the new game object onto it
let newGameIdArray = new Array();
newGameIdArray.push(newGameObject);
// Once pushed the array has the OLD game number in it . . . so 123 - WHY?!?!
console.log('newGameObjectArray', newGameIdArray);
setGameNumberFields(newGameIdArray); // updates with the 123 game number. . .
}; // end handleGameNumberChange
So in the method, I deep copy the gameNumberFields into a mutable object. I then update the object with the new gameNumber (from 123 to 999) and all works when I print it out with my console.log for newGameObject.
As soon as I push this object in the new Array - it changes back to 123! Can anyone see a flaw in my code here?
When I finally do call setGameNumberFields - it does set the state (I have a useEffect that prints out the values) but again, its always the OLD values.
Any help is welcome and appreciated!
I'm facing this issue in my react app:
The application is used for manage storage of a shop, there is one page in which user can add a new obj ( with name , quantity etc.) and there is a page used for UPDATE the obj.
In the "update" page I display the same form of the "new" page but with the current value as placeholder, so that the user can see what value is actually set and change just one or few of the values and leave the others as they are.
The problem is that when the user interact with the input ( like start typing then cancel ) the placeholder disappear and the value is updated as empty.
Now I would like that if user leaves the field empty after interacting with it, the placeholder should appear again, and I would like to make that if the input is left empty then it would not be updated or should be updated with the previous value.
I'm using antd library, so all inputs and stuff are taken from there.
const [data, setData]=useState({
numero: 0,
date: '' ,
nome: "",
...
//get current data
useEffect(() =>get(child(dbRef,'test/' + searchParams.get('id'))).then((snapshot)=>{
if(snapshot.exists()){
setData(snapshot.val())
console.log('[CONVERTED-DATA]',snapshot.val(), '[stato]', data);
}else{
console.log('[GET] NO data available')
}
}).catch((error)=>{
console.log(error)
})
, [])
//now "data" is populated with the values from db
function onChange(e) {
const value = e.target.value ;
setData({
...data,
[e.target.name]: value
});
console.log("[CHANGE-VALUE]", value);
console.log("[event]", e);
}
<Form>
<Form.Item
name="nome"
label="Nome"
rules={[ { type: "string", min: 3 }]}
initialValue={data.nome}
>
<Input
placeholder={data.nome}
value={data.nome}
name="nome"
onChange={onChange}
className="update-input"
/>
</Form.Item>
... more inputs
So I have two modals that I am using one of them was already implemented and behaves as expected however when I've added the other modal depending on the condition of if there is any true value when mapping over the array the way it works right now both modals show when there is a true value. I think this is because there are multiple false values returned from my .includes() function before the true appears. I think a good solution for this would be to make an array of all the values returned when I run .includes() on the entries then I can check that array for any true values but I cant seem to get the values into an array. When I try and push them into an array they just all push into their own separate arrays. This may be the wrong approach if it is can you explain what a better approach would be:
const checkPending = () => {
if(entries){
entries.map(descriptions => {
const desc = descriptions.description
//check if there are any pending tests
const check = desc.includes("pending")
//if the check returns true show the pending modal if it doesnt set the other modal to true
if(check === true){
setShowModal(false)
setShowPendingM(true)
}else{
setShowModal(true)
}
})
}
}
return(
<Button
onClick={() => checkPending()}
className={`${styles.headerButton} mr-2`}
>
Add File
<Plus />
</Button>
)
setShowModal & setShowPendingM are both passed from a parent component as props. They are both initialized as false. The most straightforward question I can pose is is there any way to say if there are any true values returned from .includes then do something even if there are false values present
I think this is how your checkingPending method should look like.
const checkPending = () => {
if(entries){
let pending = false;
entries.forEach((descriptions) => {
const desc = descriptions.description
if(desc.includes('pending')){
pending = true;
}
});
if(pending) {
setShowModal(false);
setShowPendingM(true);
} else {
setShowModal(true);
setShowPendingM(false);
}
}
}
Let me know if you have any additional questions.
My users complain that they can enter new value (one that is not included in the options) even when that is not exactly the case.
When you input text, without selecting item from options and then leave the typeahead, the text stays there, which leads users to believe that new value (one that is not included in options) can be entered.
What would be the right way to deal with this?
I am quite new to frontend development, so the answer might actually be obvious.
One way to address this is to clear the typeahead when the user blurs the input unless they've made a valid selection. Here's an example:
https://codepen.io/anon/pen/qLBaYK
class BlurryTypeahead extends React.Component {
state = {
selected: [],
};
render() {
return (
<Typeahead
onBlur={this._handleBlur}
onChange={this._handleChange}
options={['one', 'two', 'three']}
ref={typeahead => this._typeahead = typeahead}
selected={this.state.selected}
/>
);
}
_handleBlur = () => {
// Check if there are selections.
if (!this.state.selected.length) {
// Clear the component if not.
this._typeahead.getInstance().clear();
}
}
_handleChange = (selected) => {
// Track the selected state
this.setState({ selected });
}
}
I am creating a react madlibs app, and I want to update this.state.blanks array one item at a time when the user inputs words. I think I must be having trouble binding(but I thought having the fat arrow function bound it)? or I've just approached the problem the wrong way.
with my code the way it is now, I consistently get the error "cannot read property 'value' of undefined" (referring to the e.target.value in the handleEnterWord function)
here is what the problematic section of my code looks like right now.
state = {
error: null,
isLoaded: false,
title: null,
blanks: [noun, adjective, verb, etc],
value: [],
filledBlanks: []
};
handleEnterWord = (e, index) => {
const word = e.target.value
const newBlanks = [...this.state.blanks]
newBlanks[index] = word
this.setState({blanks: newBlanks})
console.log(word, newBlanks)
}
render() {
return (
<div className="App">
<button onClick = {this.handleNewMadlib}>New MadLib</button>
<h1>{this.state.title}</h1>
{this.state.blanks.map((blank, key) => {
return <input key={key} placeholder={blank} onChange={()=>this.handleEnterWord(e, key)}/>
})}
EDIT: I have added some values to the blanks array because I thought the question was a little ambiguous--this will be filled in by an API call in the actual app
Any help/advice at all is welcome.
thanks in advance :)
I believe your problem is in
onChange={()=>this.handleEnterWord(e, key)}
You should pass the event to the function like this
onChange={(e)=>this.handleEnterWord(e, key)}