Reactjs Instant search - javascript

I have a JSON schema which I'm mapping through the page and then rendering. Now I want to filter through an only search query and render only the search results.
Listing.jsx
<div id="searchbar">
<Hero>
<Section>
<Container>
<Heading style={{ color: "white" }}>SEARCH</Heading>
<Field>
<Control>
<Input
onChange={this.onChangeSearch}
name="query"
type="text"
placeholder="Enter query"
value={query}
/>
</Control>
</Field>
</Container>
</Section>
</Hero>
</div>
<div>
{pageItems.map(data => (
<div key={data.id}>
{data.status === true ? (....) : (...)}</div>}
How can I show only relevant search results in instant search/real-time search?
As per comments/suggestions, I'd like the search based on a specific array or entire JSON object to search.
This is my onChange event which returns the whole JSON object in the console.
onChangeSearch = evt => {
this.setState({
[evt.target.name]: evt.target.value
});
this.state.items.map(data => {
return console.log(data);
});
};

Related

How can I make my array into a map when saved in Firestore?

I have dynamic text fields that would repeat every time I'll click a button. As of now, the colorList is an array, and this is how it shows in the console I plan to save this in firestore.
console
Firebase
I wanted to store this in Firebase as map so it'll be something like red: 10 since I would be updating these stocks red
Codes
const [colorList, setColorList] = useState([{ color: "", colorStocks: "" }]);
{colorList.map((singleColor, index) => (
<div key={index}>
<div style={{ display: "flex" }}>
<Grid item>
<TextField
label="color"
name="color"
type="text"
id="color"
required
value={singleColor.color}
onChange={(e) => handleColorChange(e, index)}
/>
</Grid>
<br />
<Grid item >
<TextField
label="Stocks"
name="colorStocks"
type="number"
id="colorStocks"
required
value={singleColor.colorStocks}
onChange={(e) => handleColorChange(e, index)}
/>
</Grid>
</div>
<br />
//buttons here to add and remove textfields
</div>
))}
You can use Array.prototype.reduce() for this:
const colorMap = colorList.reduce(function(map, obj) {
map[obj.color] = obj.colorStocks;
return map;
}, {});

Mapped nested component doesn't work peopetly (React Js)

I have a list of items mapped to be displayed on my "allItems" page. Now every Item has a button that fires up a modal with the specs of the item, but this modal display the same value for all the item (the last one in the array).
I tried to pass the id in toggle func but it doesn't work.
Anyone knows how can I display the same data in the Card and the Modal?
Here's my code:
state = {
modal: false,
}
toggle = () => {
this.setState({
modal: !this.state.modal
})
}
render(){
return(
{rooms.map(({ _id, name, descr, prezzo }) => (
<>
<Card key={_id} className="rooms-card-template">
<CardImg />
<CardBody>
<CardTitle>{name}</CardTitle>
<CardText>{descr}</CardText>
<CardSubtitle>{prezzo}$/notte</CardSubtitle>
<Button onClick={this.toggle}>Apri Annuncio</Button>
<Modal isOpen={this.state.modal} toggle={this.toggle}>
<ModalHeader >{name}</ModalHeader>
<ModalBody>
{descr}
<h5 style={{ paddingTop: "10px"}}>Riepilogo prenotazione</h5>
<Form>
<FormGroup>
<Label>Struttura:</Label>
<Input value={name}/>
</FormGroup>
<FormGroup>
<Label>Ospiti:</Label>
<Input type="select"name="ospiti" id="ospiti">
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
<option>5</option>
<option>6</option>
<option>7</option>
<option>8</option>
<option>9</option>
</Input>
</FormGroup>
<FormGroup>
<Label>Check in</Label>
<Input type="date" name="checkin-date" id="checkin-date" placeholder="Check in" />
</FormGroup>
<FormGroup className="rooms-checkout">
<Label>Check out</Label>
<Input type="date" name="checkout-date" id="checkout-date" placeholder="Check out" />
</FormGroup>
{ isAuth ? userAuth : userUnauth }
</Form>
</ModalBody>
</Modal>
</CardBody>
</Card>
</>
))}
)
}
Issue
You've a single boolean modal state that all the modals cue from. When this.state.modal is true then a modal is rendered and opened for each element being mapped.
Solution
Instead of storing a boolean value for whether or not a modal should be open you should store an id when you want a specific modal to open.
state = {
modal: null // <-- null, non-id state value
};
toggle = (id) => () => { // <-- curried function handler
this.setState((prevState) => ({
modal: prevState.modal === id ? null : id // <-- set new id or toggle off
}));
};
render() {
return (
<>
{rooms.map(({ _id, name, descr, prezzo }) => (
<Card key={_id} className="rooms-card-template">
...
<CardBody>
...
<Button
onClick={this.toggle(_id)} // <-- pass id
>
Apri Annuncio
</Button>
<Modal
isOpen={this.state.modal === _id} // <-- open if id is match
toggle={this.toggle(_id)} // <-- pass id
>
...
</Modal>
</CardBody>
</Card>
))}
</>
);
}

How do I change the color of the text "labels" of the Form elements of a simple component of a React JS application?

I have a simple React component called "Login.js" that uses forms, and it returns the following:-
return (
<div className="form-container">
<Form onSubmit={onSubmit} noValidate className={loading ? 'loading' : ''}>
<h1>Login</h1>
<Form.Input
label="Username"
placeholder="Enter your username..."
name="username"
type="text"
value={values.username}
error={errors.username ? true : false}
onChange={onChange}
/>
<Form.Input
label="Password"
placeholder="Enter your password..."
name="password"
type="password"
value={values.password}
error={errors.password ? true : false}
onChange={onChange}
/>
<Button type="submit" primary>
Login
</Button>
</Form>
{Object.keys(errors).length > 0 && (
<div className="ui error message">
<ul className="list">
{Object.values(errors).map((value) => (
<li key={value}>{value}</li>
))}
</ul>
</div>
)}
</div>
);
How do I change the colors of the text labels "Username" and "Password"? Do I need to create another CSS file called "Login.css" within the components folder, import that into "Login.js", and make the changes there? If so, how do I do that? Please explain.
You can create a Style variable in the render method and then access it in the JSX
class MyForm extends React.Component {
render() {
const usernameStyle = {
color: "green",
};
const passwordStyle = {
color: "blue",
};
return (
<>
<Form.Input style={usernameStyle} ... />
<Form.Input style={passwordStyle} ... />
</>
);
}
}
Else, you can also define style inline, as varaible or via a separate css file.
You can find all the options here
The easiest way to do this is to use style={{color: "red"}} nested within your tag. Like:
<Form.Input
label="Username"
placeholder="Enter your username..."
style={{color: "red"}}
/>
The website linked below talks about css in react
https://www.w3schools.com/react/react_css.asp

Cannot read property 'map' of undefined - Error from ReactJS

Error Message:
Error: Cannot read property 'map' of undefined
React component:
const checkBox = props => {
return (
<div>
<label htmlFor={props.name} className='form-label'>
{props.title}
</label>
<div className='checkbox-group'>
{
props.options.map(option => {
return (
<label key={option}>
<input
className='form-checkbox'
id={props.name}
name={props.name}
onChange={props.handleChange}
value={option}
checked={props.selectedOptions.indexOf(option) > -1}
type='checkbox'
/>{' '}
{option}
</label>
)
})
}
</div>
</div>
)
}
In my code is anything going wrong? If yes please let me know. Can someone help me out from this?
The error
Cannot read property 'map' of undefined
Is thrown when the map function in the comment list component is executed.
A question comment references a tutorial showing how to build a form and its sub-components. A couple of the components include examples of how to pass props, but that's missing from <Checkbox/>.
To fill that gap, here's an example of how you might expect to use <Checkbox/>. I didn't read the article in its entirety, so I'm hoping you can help correct any mistakes I've made here and it gets you started on your own development.
<Checkbox
title={'Skills'}
name={'skills'}
options = {this.state.skills} <!-- array of skills or empty array -->
selectedOptions = {this.state.newUser.skills} <!-- array of skills or empty array -->
handleChange = {this.handleInput}
/>
You could also use a simple fallback like.
const checkBox = props => {
const { options, name, titlem, selectedOptions, handleChange } = props
return (
<div>
<label for={name} className="form-label">
{title}
</label>
<div className="checkbox-group">
{(options || []).map(option => {
return (
<label key={option}>
<input
className="form-checkbox"
id={name}
name={name}
onChange={handleChange}
value={option}
checked={selectedOptions.indexOf(option) > -1}
type="checkbox"
/>{" "}
{option}
</label>
);
})}
</div>
</div>
);
};
const checkBox = ({ options, name, title, selectedOptions, handleChange }) => {
return (
<div>
<label htmlFor={name} className='form-label'>
{title}
</label>
<div className='checkbox-group'>
{
options && options.map(option => {
return (
<label key={option}>
<input
className='form-checkbox'
id={name}
name={name}
onChange={handleChange}
value={option}
checked={selectedOptions.indexOf(option) > -1}
type='checkbox'
/>{' '}
{option}
</label>
)
})
}
</div>
</div>
)
}

Field array with one field at initial

I am trying to use the concept of field array because in my app a user should be able to fill multiple value for same kind of field. I could do as per redux-form field array example, however, in an example there is no initial field we have to first click on add member and then only we can have the field to fill the value but i need one field initially and then add further field if user wants to.
I tried from the redux-form example but its not allowing me to input the value at all. Here is the demo
https://codesandbox.io/s/n47qr2pvzl
The format of that field value should be like this
general: {
general_information: {
members: [
{
name: ''
},
{
name: ''
}
]
}
}
Here is the code
const renderMembers = ({ fields, meta: { touched, error, submitFailed } }) => (
<ul>
<li>
<button type="button" onClick={() => fields.push({})}>
Add Member
</button>
{(touched || submitFailed) && error && <span>{error}</span>}
</li>
{fields.map((member, index) => (
<li key={index}>
<button
type="button"
title="Remove Member"
onClick={() => fields.remove(index)}
/>
<h4>Member #{index + 1}</h4>
<Field
name={`${member}.name`}
type="text"
component={renderField}
label="Name"
/>
</li>
))}
</ul>
);
const FieldArraysForm = props => {
const { handleSubmit, pristine, reset, submitting } = props;
return (
<form onSubmit={handleSubmit}>
<Field
name="general.general_information.clubName"
type="text"
component={renderField}
label="Club Name"
/>
<Field
name="general.general_information.members.name"
type="text"
component={renderField}
label="Name"
/>
<FieldArray
name="general.general_information.members"
component={renderMembers}
/>
<div>
<button type="submit" disabled={submitting}>
Submit
</button>
<button type="button" disabled={pristine || submitting} onClick={reset}>
Clear Values
</button>
</div>
</form>
);
};
According to Redux-Form, we can set the initial fields by specifying it like (in your case):
export default reduxForm({
form: "fieldArrays", // a unique identifier for this form
validate,
initialValues: {"general": {
"general_information": {
"members": [
{}
]
}
}
}
})(FieldArraysForm);
Here is the live demo
Hope it helps :)

Categories