I have a SearchBarComponent that looks like this
const SearchBarComponent = ({inputStyle, searchIconSize, onChange, formClass, query, name, onClick, formContainerClass}) => {
return (
<div className={formContainerClass}>
<form className={formClass}>
<div class="form-group">
<input type="text" value={query} onChange={onChange} name={name} class="form-control shadow-none" placeholder="Search your dream car.." style={inputStyle}/>
<Link to="/car-list">
<BiSearchAlt2 onClick={onClick} className="search-icon" size={searchIconSize}/>
</Link>
</div>
</form>
</div>
)
};
export default SearchBarComponent;
I have a landing screen with the SearchBarComponent where a user can enter a search query, when they click it, it should populate the SearchBarComponent in the results page (Which is in a different component) so that it moves the props to the other SearchBarComponent and displays the results.
I don't know if it makes sense but here's a small snippet of what I'm looking for but struggling to implement.
https://codesandbox.io/s/epic-bhabha-p5htt4?file=/src/App.js
Related
I have this WP API data that I'm fetching in to a component called "HostingCard". I am mapping through this component which renders three cards. While mapping through these I am assigning a key to each of them.
`{hostings.map((hosting) => (
<HostingCard key={hosting.id} hosting={hosting} setHosting={setHostings} />
))}`
Each card has one of these titles "Pro", "Standard" and "Basic".
I made it so that once a card is clicked a new component appears. This component is called "ContactFormular".
Now in the "ContactFormular" component I want to display the information that was on the card that was clicked. is this possible?
Here's the code that opens a new component once the card/button is clicked:
import ContactFormular from './ContactFormular'
const HostingCard = ({post, handleSubmit, hosting, setHosting, showContactDialog, setShowContactDialog, ssl, setPro, pro, key}) => {
return (
<div className='noselect hosting-options'>
<input type="radio" id={post.acf.hosting} name="startup" />
<div className='card selected-card'>
<form onSubmit={handleSubmit}>
<label for={post.acf.tilvalg} className='label'>
<div className='card-header'>
<h5>{hosting.acf.title}</h5>
<p>{hosting.acf.beskrivelse}</p>
</div>
<div className='pakke-detaljer'>
<div>
<p style={{display: hosting.acf.deltaljer ? 'block' : 'none'}}>{hosting.acf.deltaljer}</p>
</div>
</div>
<div className='button-header' onClick={() => setPro(false)}>
<button className='btn' onClick={() => setShowContactDialog(true)}>Vælg</button>
</div>
</label>
</form>
</div>
<ContactFormular key={hosting.id} post={post} hosting={hosting} setHosting={setHosting} showContact={showContactDialog} setShowContact={setShowContactDialog} handleSubmit={handleSubmit} ssl={ssl} pro={pro} setPro={setPro}/>
</div>
)
}
It looks like you're passing in showContactDialog as a parameter and using that to decide whether or not to show this new component right? That means you need showContactDialog to be true for only the one you clicked on, and false for the others. ie each component needs a different state variable. It looks like you might be sharing the same state variable between all components. It's impossible to tell unless you share a reproducible example
I am building a user page, in which i am getting user info from state itself using useState hook of redux.
import React, { useState, useEffect } from "react";
import profileImage from "../../resources/images/defaultProfile.png";
import { useSelector, useDispatch } from "react-redux";
import { userActions } from "../../state/actions";
const User = () => {
const [isEditable, setIsEditable] = useState(false);
const onChange = (e) => {
setUser({
...user,
[e.target.name]: [e.target.value],
});
};
const onSubmit = () => {
if (!isEditable) {
setIsEditable(!isEditable);
} else {
//TODO update user data here
}
};
const [user, setUser] = useState(useSelector((state) => state.user.user));
return (
user !== null && (
<div className="container-fluid">
<div className="row">
<div className="col-md-9 border border-primary">user preference</div>
<div className="col-md-3 border border-primary">
<div className="row-cols-md-3 text-center">
<img
src={profileImage}
alt="Profile image"
style={{ width: "60%", height: "70%" }}
className="border rounded-circle"
/>
<form onSubmit={onSubmit} style={{ width: "100%" }}>
<div className="mb-3">
<label htmlFor="userName" className="form-label">
User Name
</label>
<input
type="text"
name="name"
id="userName"
value={user.name}
onChange={onChange}
disabled={!isEditable ? "disabled" : ""}
className="form-control"
/>
</div>
<div className="mb-3">
<label htmlFor="userEmail" className="form-label">
User Email
</label>
<input
type="email"
name="email"
disabled={!isEditable ? "disabled" : ""}
id="userEmail"
value={user.email}
onChange={onChange}
className="form-control"
/>
</div>
<div className="mb-3">
<label htmlFor="userPhone" className="form-label">
User Phone Number
</label>
<input
type="text"
disabled={!isEditable ? "disabled" : ""}
name="phoneno"
id="userPhone"
value={user.phoneno}
onChange={onChange}
className="form-control"
/>
</div>
<button type="submit">{isEditable ? "Update" : "Edit"}</button>
</form>
</div>
</div>
</div>
</div>
)
);
};
export default User;
The data is loading fine for the first time. As shown initially all my input field are disabled but once i click on edit, it changes state isEditable and enables every field and change the submit button to "update" .It's re-render the page once the state isEditable is changed. I am loading navbar by default for every page and navBar has code which reloads the value of user state in case of refresh and once the page re-renders it reloads the user global state but somehow useSelector is unable to get latest value and just returns the null value.
Observation -
once the complete re-renders happen useSelector is unable to fetch latest user data although the state has the latest value.
Can somebody please suggest what approach should i choose to overcome the following scenerio.
Never do
useState(useSelector(...));
It does not do what you expect.
useState is initialized once with the argument you put into it - so at first render, it will "capture" the value the selector returns at that point in time. But it will never update the state once the return value from useSelector changes. The local state is initialized after all.
Well i was surfing internet for the following issue and i found this.
https://dmitripavlutin.com/react-forms-tutorial/
" By default, when clicking the form’s Submit button, the browser performs a full-page POST request to the URL specified in the action attribute of the . But having the form controlled by React, you can prevent browser’s default behavior by attaching an event handler to onSubmit event and calling event.preventDefault(). "
And based on this i bring my button out of the form, since now no complete post request would be called and hence it started working.
Frankly i am still not sure, earlier why it was working fine after second click.
Before Clicking anything text field should be disable . when after the radio button selected my text field must be enable.
This is the working solution of your question.
class App extends React.Component {
state = {
isRadioSelected: true
};
changeHandler = () => {
this.setState({ isRadioSelected: false });
};
render() {
return (
<div className="App">
<h3>Input text is {this.state.isRadioSelected ? 'Disabled': 'Enabled'}</h3>
<input type="text" disabled={this.state.isRadioSelected} />
<br />
<label>Select Radio Button</label>
<input type="radio" onChange={this.changeHandler} />
</div>
);
}
}
ReactDOM.render(<App/>, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id='root' />
Your description is pretty vague and you don't have any code samples, but here's likely what you want to do:
Make the radio button a controlled component, so that you can access it's value within React's state.
Tie the input's disabled attribute to the value of that state field.
It also seems like you want a checkbox, and not a radio button, since a radio button cannot be untoggled if there is only a single radio button.
This code will likely not work as-is (I haven't run it), but should provide a starting idea:
function Tester() {
const [radioValue, setRadioValue] = useState(false)
return (
<div>
<input type="radio" onClick={(e) => setRadioValue(e.target.value)} value={radioValue} />
<input type="text" placeholder="your input box" disabled={!radioValue} />
</div>
)
}
Summary
I want to understand how the tabulation navigation works on browser, in order to perform custom input with suggestion field on React.
Objective
The objective is to provide 2 custom input to the use with suggestion dropdown. When I click to my input, the dropdown shows correctly and I can navigate through the tabulation key to my suggestions. But when I try to navigate to the next input, the dropdown shows but I can't navigate through my second dropdown suggestion.
Code example
I have the following JSX code:
class InputDropdown React.Component {
render() {
return(<div>
<div id="input1" className="input-wrapper" onMouseEnter={...} onMouseLeave={...} onBlur={...}>
<input className={"input"}
value={this.state.search_input}
onKeyDown={(e) => e.keyCode==13?this.props.validate(this.state.search_input)}
onFocus={this.setState(display_dropdown_input1: true)}
/>
<div className={"dropdown-wrapper" + this.state.display_dropdown_input1?"":"hidden"}>
{this.props.suggestion.map((suggestion, index) =>
<div className="suggestion"
tabIndex={0}
onKeyDown={(e) => e.keyCode==13?this.props.validate(suggestion.text)}
onBlur={index+1==this.props.suggestion.length?this.setState({display_dropdown_input1:false})}
>{suggestion.text}</div>)}
</div>
</div>
<div id="input2" className="input-wrapper" onMouseEnter={...} onMouseLeave={...} onBlur={...}>
<input className={"input"}
value={this.state.search_input}
onKeyDown={(e) => e.keyCode==13?this.props.validate(this.state.search_input)}
onFocus={this.setState(display_dropdown_input2: true)}
/>
<div className={"dropdown-wrapper" + this.state.display_dropdown_input2?"":"hidden"}>
{this.props.suggestion.map((suggestion, index) =>
<div className="suggestion"
tabIndex={0}
onKeyDown={(e) => e.keyCode==13?this.props.validate(suggestion.text)}
onBlur={index+1==this.props.suggestion.length?this.setState({display_dropdown_input2:false})}
>{suggestion.text}</div>)}
</div>
</div>
</div>)
}
}
Question
It's as if the tabulation navigations road is prepared on the first tabulation pressed and if element appear after this press they are not taken in count.
Is it possible to perform it in React?
Working on the setting security questions part of the authentication. The server responds with a list of the 20 or so questions in the form of an array. I can get the form and select box to render, but only one option at a time by specifying the index.
If I try to send the entire array I get an undefined error. Tried to do a for loop in the ` to iterate through each index, which generated an error.
I'm trying to figure out how to pass the entire array so it makes an option for each entry in the array.
This is what I have so far:
// ./set_security_questions.js
// This renders errors regarding the form inputs
renderField(field) {
const {
label,
placeholder,
type,
name,
questions,
meta: {
touched,
error
}
} = field;
return (
<div className='form-group'>
<label>{label}</label>
<select className='form-control' name={name}>
<option value={questions}>{questions}
</option>}
</select>
<input
className='form-control'
type={type}
placeholder={placeholder}
{...field.input}
/>
<div className='text-danger'>
{touched ? error : ""}
</div>
</div>
);
}
// The main body to be rendered
render() {
if (this.props.permitRender) {
const { handleSubmit } = this.props;
return (
<div>
<h3>Set Security Questions</h3>
<p>Please select two security questions that will be easy for you to remember.</p>
<form onSubmit={handleSubmit(this.onSubmit.bind(this))}>
{this.renderAlert()}
<Field
questions={this.props.questions.data.security_question}
label='Question 1'
placeholder='Answer 1'
name='a1'
type='text'
component={this.renderField}
/>
<Field
label='Question 2'
placeholder='Answer 2'
name='a2'
type='text'
component={this.renderField}
/>
<button type="submit" className="btn btn-primary">Submit</button>
</form>
</div>
);
} else if (!this.props.permitRender) {
return (
<div> { this.renderAlert() } </div>
);
}
}
In addition, my JSON that comes back from the server looks pretty strange, so I will need to iron that out, but still wondering how to pass an array into the Form. this.props.questions.data:
data:
id: 123
key: "key_request"
security_q1: null
security_q2: null
security_question: Array(29)
0: {security_question: "In what city or town did you meet your spouse / partner?"}
1: {security_question: "In what city or town did your mother and father meet?"}
2: {security_question: "In what town or city was your first full time job?"}
3: {security_question: "What is the first name of your spouse's father?"}
......
Here is an example I'm currently using to populate a set of checkboxes. There isn't any special logic going on in the checkbox component, I just am using custom html for styling purposes.
Here is my data, a simple array:
const env = {
FONT_FORMATS: ['OTF', 'TTF', 'WOFF', 'WOFF2']
}
Here is the code in the render() function for my component. I'm storing each item in the Redux form under the object key -> fileTypes.
<ul className='tags'>
{envConfig.FONT_FORMATS.map((tag: string) => (
<Field
key={tag}
value={tag}
name={`fileTypes.[${tag}]`}
id={tag.toLowerCase().replace(' ', '_')}
type='checkbox'
component={checkBox}
label={tag}
/>
))}
</ul>
I hope this helps you out!