React: array as props shows as undefined - javascript

I'm trying to pass an array called myitems as props to a child component, but I get an error saying that options is undefined in the Child component. Not sure what's going on here. Any help will be highly appreciated.
Child component:
import React from 'react';
const Dropdown = ({className, options}) => {
return (
<>
<select className={className}>
{options.map((el,i) => (<option key={i}>{el.type}</option>))}
</select>
</>
)
}
export default Dropdown;
Parent component:
import React from 'react';
import Dropdown from './Dropdown'
const BudgetInput = ({ descValue, budgetValue, onDescChange }) => {
const myItems = [{ type: '+' }, { type: '-' }];
return (
<>
<Dropdown
className="add__type"
options={myItems}
/>
<input
type="text"
className="add__description"
placeholder="Add description"
value={descValue}
onChange={onDescChange}
/>
<input
type="number"
className="add__value"
placeholder="Value"
value={budgetValue}
//onChange={}
/>
<Dropdown
className="add__category"
/>
<button onClick={handleInput}>Enter</button>
</>
)
}
export default BudgetInput;

You're not passing an options prop to the second Dropdown instance, which is why you're getting the error
<Dropdown
className="add__category"
/>

Related

X is not a function in React JS

In my App.js component I have this state :
const [searchText, setSearchText] = useState('');
I have passed this into the Search component as a prop to update the text that I write in the search bar that I have created in the search component.
This is the error that is coming : bundle.js:461 Uncaught TypeError: props.handleSearchNote is not a function
Here is how i have passed in the function in App.js:
And this is my search component:
import React from 'react'
import { MdSearch } from 'react-icons/md'
const Search = (props) => {
return (
<div className='search'>
<MdSearch className='search-icons' size='1.3em' />
<input
onChange={(event) =>
props.handleSearchNote(event.target.value)
}
type='text'
placeholder='type to search...'
/>
</div>
);
};
export default Search;
This is where I have passed the Search component in App.js
return (
<>
<div className='container'>
<Search handlSearchNote={setSearchText} />
{console.log(searchText)}
<NotesList
notes={notes.filter((note) => note.text.toLowerCase().includes(searchText))}
handleAddNote={addNote}
handleDeleteNote={deleted} />
</div>
</>
);
}
export default App;
You're assigning setSearchText to handlSearchNote not handleSearchNote. You forgot the 'e' in handle. This happens to me all the time😅.

Using react-number-format: cannot type more than one symbol at once

I am using react-number-format package inside of my TextField (material-ui). It is having strange behavior and not letting me put more than one symbol at once in the TextField. When I start typing after first click the Field is not focused anymore. I have used the same thing in other projects and it is working fine but here I cannot see from where the problem is coming. Here is the sandbox:
https://codesandbox.io/s/little-cherry-ubcjv?file=/src/App.js
import React,{useState} from 'react'
import { TextField} from "#material-ui/core";
import NumberFormat from "react-number-format";
export default function App() {
const [minAssets, setMinAssets] = useState();
const NumberFormatCustom = (props) => {
const { inputRef, onChange, ...other } = props;
return (
<NumberFormat
{...other}
getInputRef={inputRef}
onValueChange={(values) => {
onChange({
target: {
name: props.name,
value: values.value,
},
});
}}
thousandSeparator
isNumericString
prefix="$"
/>
);
};
return (
<div className="App">
<TextField
label="Min Assets"
value={minAssets}
onChange={(e) => setMinAssets(e.target.value)}
name="minAssets"
variant="outlined"
id="Minimum-Income-filter"
InputProps={{
inputComponent: NumberFormatCustom,
}}
/>
</div>
);
}
In your case you don't really need the onValueChange prop on the NumberFormat component since you already have an onChange on the TextField component that update the minAssets state.
So you can directly use this minAssets as the value of the prop value from NumberFormat like:
return (
<NumberFormat
{...other}
value={minAssets}
getInputRef={inputRef}
thousandSeparator
isNumericString
prefix="$"
/>
);

Cannot read property 'props' of undefined in react, pass data from parent to child

I'm sitting with this for a while and wondering if there is any possibility of passing the state from parent to child in this case?
I need this id to give input and label an unique id couse this component is used multiple times.
Thanks for any advice.
Parent:
<FileUpload key={el.id} parentCallback={this.callback(el.id)} id={el.id}/>
Child:
import React, { Fragment, useState } from 'react';
import Message from './Message';
import Progress from './Progress';
import axios from 'axios';
const FileUpload = ({ parentCallback }) => {
return (
<Fragment>
<form className="image__uploadForm" onSubmit={onSubmit}>
{this.props.id} // Causes error props undef
<div className='image__upload'>
<input
type='file'
className='input__uploadFile'
id='uploadFile'
accept="image/*"
onChange={onChange}
/>
<label className='input__uploadFile--label' htmlFor='uploadFile'>
{filename}
</label>
{!file ? (
null
) :
<input
type='submit'
value='Upload'
/>
}
</div>
</form>
</Fragment>
);
};
export default FileUpload;
As #ajobi said, this will not be defined in a functional component using the arrow syntax.
You can solve this three ways:
1. Use the rest syntax to gather all props except parentCallback into a variable called props:
const FileUpload = ({ parentCallback, ...props }) => {
...
{props.id}
2. Spread all props into their own variables:
const FileUpload = ({ parentCallback, id }) => {
...
{id}
3. Spread none of the variables and use the props object when using all props in your component:
const FileUpload = (props) => {
...
{props.id}
...
props.parentCallback
You can not pass your callback like this parentCallback={this.callback(el.id)} because it will be executed instantly by render.
You could try to pass in an error function like parentCallback={() => this.callback(el.id)} and call it in the submit function
Id is undefined because Id is a key word and will be not passed
Parent:
<FileUpload key={el.id} parentCallback={() => this.callback(el.id)} {...el}/>
Child:
import React, { Fragment, useState } from 'react';
import Message from './Message';
import Progress from './Progress';
import axios from 'axios';
const FileUpload = ({ parentCallback, id }) => {
const onSubmit = () => {
return parentCallback()
}
return (
<Fragment>
<form className="image__uploadForm" onSubmit={onSubmit}>
{id}
<div className='image__upload'>
<input
type='file'
className='input__uploadFile'
id='uploadFile'
accept="image/*"
onChange={onChange}
/>
<label className='input__uploadFile--label' htmlFor='uploadFile'>
{filename}
</label>
{file && <input type='submit' value='Upload'/>} //Tip: If you work with && you do not need to return null
</div>
</form>
</Fragment>
);
};
export default FileUpload;
Otherwise you can pass your function like:
Parent:
<FileUpload key={el.id} parentCallback={this.callback} {...el}/>
Child:
....
const FileUpload = ({ parentCallback, id }) => {
const onSubmit = () => {
return parentCallback(id)
}
return (....)
}

How do I reference a input element from higher order component

I would like to access the input element from my HOC. How can I achieve this?
const TextInput = (props) => {
const allowed = ['readOnly','tabIndex','placeholder'];
const filteredProps = filterProps(props,allowed);
return (
<div>
<label>{props.field.Name}</label>
<input type="text" ref={props.inputRef} key={props.field.Id} className="form-control" id={props.field.Id} name={props.field.Name}
value={props.value}
onChange={props.onChange}
onKeyDown={props.onKeyDown}
{...filteredProps}
/>
</div>
);
}
TextInput.propTypes = {
fieldMetadata: PropTypes.object,
isValid: PropTypes.bool
}
export default withInputMask(withRequired(withReadOnly(withMinMax(withHidden(TextInput)))));
I have tried a few things but this is the latest attempt.
Inside the withInputMask render method I have inserted the following.
return (
<div>
<Component {...this.props} inputRef={el=> this.inputElement=el} isValid={isValid} onChange={this.onChange} placeholder={inputMaskPattern} />
{hasErrors && <span className={hasErrors}>{error}</span>}
</div>
);
}
}
};
export default withInputMask;
when I open the react dev tools and click on withInputMask component this is what I see.

Custom input - Redux form

I have the following CustomInput component:
import React from 'react';
const CustomInput = props => (
<div className="form-group">
<label className="form-label">{props.title}</label>
<input
className="form-input"
name={props.name}
type={props.inputType}
value={props.content}
onChange={props.controlFunc}
placeholder={props.placeholder}
/>
</div>
);
CustomInput.propTypes = {
inputType: React.PropTypes.oneOf(['text', 'number']).isRequired,
title: React.PropTypes.string.isRequired,
name: React.PropTypes.string.isRequired,
controlFunc: React.PropTypes.func.isRequired,
content: React.PropTypes.oneOfType([
React.PropTypes.string,
React.PropTypes.number,
]).isRequired,
placeholder: React.PropTypes.string,
};
export default CustomInput;
And this is my form:
import React, { PropTypes } from 'react';
import { Field, reduxForm } from 'redux-form';
import CustomInput from '../components/CustomInput';
const renderMyStrangeInput = field => (
<CustomInput
inputType={'number'}
title={'How many items do you currently own?'}
name={'currentItems'}
controlFunc={param => field.input.onChange(param.val)}
content={{ val: field.input.value }}
placeholder={'Number of items'}
/>
);
class ItemsForm extends React.Component {
constructor(props) {
super(props);
}
render() {
const { handleSubmit } = this.props;
return (
<form className="container" onSubmit={handleSubmit}>
<h1>Nuevo Pedido</h1>
<Field name="myField" component={renderMyStrangeInput} />
<div className="form-group">
<button type="submit" className="btn btn-primary input-group-btn">Submit</button>
</div>
</form>
);
}
}
ItemsForm.propTypes = {
};
ItemsForm = reduxForm({
form: 'Items',
})(ItemsForm);
export default ItemsForm;
I can render my component, but there are some issues with the content type. First, if I set the CustomInput to accepts numbers I get:
he specified value "[object Object]" is not a valid number. The value must match to the following regular expression: -?(\d+|\d+\.\d+|\.\d+)([eE][-+]?\d+)?
Second, if I set the inputType to text, it renders a:
[object Object]
so, the console is giving the following warning:
Warning: Failed prop type: Invalid prop `content` supplied to `CustomInput`.
How can I set the content properly?
I think the issue is that you are trying pass strings as objects
<CustomInput
inputType="number"
title="How many items do you currently own?"
name="currentItems"
controlFunc={param => field.input.onChange(param.val)}
content={field.input.value}
placeholder="Number of items"
/>
You are passing object via props and you must pass string or number.
content={{ val: field.input.value }} // no!
content={field.input.value} // yes! :)

Categories