I am trying to use react-hook-form to simply generate some data from two material UI text fields and display the data in the console, but the when clicking the submit button I cannot see anything in the console.log, this is the code:
import React from 'react';
import TextField from '#material-ui/core/TextField';
import Button from '#material-ui/core/Button';
import { makeStyles } from '#material-ui/core/styles';
import { useForm } from 'react-hook-form';
const useStyles = makeStyles({
container: {
margin: '1rem',
'& .MuiTextField-root': {
margin: '1rem 0',
},
},
});
const GuestJoiningForm = () => {
const { register, handleSubmit } = useForm()
const onSubmit = (data) => {
console.log(data);
};
const classes = useStyles();
return (
<form onSubmit={handleSubmit(onSubmit)} className={classes.container}>
<TextField
ref={register}
label="Name"
name="name"
variant="outlined"
fullWidth/>
<TextField
ref={register}
multiline rows={3}
label="Content"
name="content"
variant="outlined"
fullWidth/>
<Button
color="primary"
variant="contained">Submit</Button>
</form>
)
};
export default GuestJoiningForm;
When I enter data into the text fields and hit the submit button, nothing happens and I would expect to see an object of the data I enter. I don't imagine its the console I'm using, but it's in Safari and the only thing I've noticed is something that says [HMR] Waiting for update signal from WDS...
Not sure if that has anything to do with it, but would really appreciate any help on this issue if you get time, thank you.
Last thing to add! I added a type={'submit'} to the button, and the console responded with empty {}, which even though didn't fix the issue I guess proves that the console is working
You need to add type attribute as submit in the Submit button.
<Button type="submit" color="primary" variant="contained">
Submit
</Button>;
You need to add inputRef prop for both the TextField components like this
<TextField
ref={register}
inputRef={register}
label="Name"
name="name"
variant="outlined"
fullWidth
/>
<TextField
ref={register}
multiline
rows={3}
inputRef={register}
label="Content"
name="content"
variant="outlined"
fullWidth
/>
Here's a sandbox for your form.
Related
I'm running into an issue with adding my own custon input after following the documentation for Autocomplete.
The error I get is "this.props.contextValue.store.getState is not a function" when adding my CustomSearchBox component. Can anyone advise what I'm doing wrong?
Usage:
<InstantSearch
searchClient={algoliaClient}
indexName="plp"
>
<CustomSearchBox /> // Errors when I add this
<Autocomplete
searchClient={algoliaClient}
placeholder="Search products"
detachedMediaQuery="none"
openOnFocus
/>
<RefinementList attribute="DIAMETER" />
<HitWrapper>
<Hits hitComponent={Hit} />
</HitWrapper>
</InstantSearch>
Custom search box component
import React from 'react';
import { connectSearchBox } from 'react-instantsearch-dom';
const SearchBox = ({ currentRefinement, isSearchStalled, refine }) => (
<form noValidate action="" role="search">
<input
type="search"
value={currentRefinement}
onChange={event => refine(event.currentTarget.value)}
/>
{isSearchStalled ? 'My search is stalled' : ''}
</form>
);
const CustomSearchBox = connectSearchBox(SearchBox);
export default CustomSearchBox;
For a new project (next.js) I'd like to add an on submit handler to a form component and map the input of the form at the bottom of the page. However, I get the typeError message claiming that the "addSpending" is not a function.
Here the code for the form component:
import styled from "styled-components";
export default function NewSpendingForm({ addSpending }) {
function handleSubmit(event) {
event.preventDefault();
const formData = new FormData(event.target);
const data = Object.fromEntries(formData);
addSpending(data);
}
return (
<StyledBody>
<StyledIntro>Please fill the form to add your spendings:</StyledIntro>
<StyledAddSpendingForm onSubmit={handleSubmit}>
<StyledFormLabel>Title</StyledFormLabel>
<StyledFormInput type="text" id="title" name="title" required />
<StyledFormLabel>Amount</StyledFormLabel>
<StyledFormInput type="number" id="amount" name="amount" step="0.01" min="0" required />
<StyledFormLabel>Date</StyledFormLabel>
<StyledFormInput type="date" id="date" name="date" required />
<StyledFormLabel>Category</StyledFormLabel>
<StyledFormSelect type="select" id="category" name="category" required >
<option>Food and Drinks</option>
<option>Clothes</option>
<option>Household</option>
<option>Entertainment</option>
<option>Gasoline</option>
<option>Restaurants</option>
<option>Others</option>
</StyledFormSelect>
<StyledFormButton type="submit">Submit</StyledFormButton>
</StyledAddSpendingForm>
</StyledBody>
);
}
And this one for the page:
import styled from "styled-components";
import NewSpendingForm from "../../components/AddSpendingForm";
export default function AddSpendingPage({ spendingInput, addSpendingInput }) {
return (
<>
<StyledHeader>
<StyledTitle>Add Spendings</StyledTitle>
</StyledHeader>
<StyledBody>
<NewSpendingForm addSpending={addSpendingInput} />
<StyledLogTitle> Your Spendings Log</StyledLogTitle>
<StyledLog>
{spendingInput.map((spendingInput) => (
<StyledLogEntry>
{spendingInput.title}
{spendingInput.amount}€
{spendingInput.date}
{spendingInput.category}
</StyledLogEntry>
))}
</StyledLog>
</StyledBody>
</>
);
}
Thanks a lot in advance!
I expected the form input to be mapped and displayed at the bottom of the page. However, after clicking on the "Submit" button I get the mentioned TypeError message.
I'm new to both React and Material-UI. While examples work fine and perfectly make sense, they all use inline elements for both triggering button and the menu itself. I want to have some conditionals. For this, I'd rather have a separate component/function that renders this or that. However as soon as I move triggering button into a function, I get
Material-UI: the `anchorEl` prop provided to the component is invalid.
The anchor element should be part of the document layout.
Make sure the element is present in the document or that it's not display none.
I looked through similar questions here, but none of them looked relevant… or I didn't get them:(
Here is the code for modified example where I want to externalize button rendering into a function (to later add conditional and what not)
export default function SimpleMenu() {
const [anchorEl, setAnchorEl] = React.useState(null);
const handleClick = event => {
setAnchorEl(event.currentTarget);
};
const Qqq = () => {
return (
<Button
aria-controls="simple-menu"
aria-haspopup="true"
onClick={handleClick}
>
Broken Menu
</Button>
)
}
const handleClose = () => {
setAnchorEl(null);
};
return (
<div>
<p> hello</p>
<Button
aria-controls="simple-menu"
aria-haspopup="true"
onClick={handleClick}
>
Open Menu
</Button>
<Qqq />
<Menu
id="simple-menu"
anchorEl={anchorEl}
keepMounted
open={Boolean(anchorEl)}
onClose={handleClose}
>
<MenuItem onClick={handleClose}>Profile</MenuItem>
<MenuItem onClick={handleClose}>My account</MenuItem>
<MenuItem onClick={handleClose}>Logout</MenuItem>
</Menu>
</div>
);
}
Here is the fiddle
https://codesandbox.io/s/material-demo-7bnki?fontsize=14&hidenavigation=1&theme=dark . I did try to use SO code snippet, but I was getting some error about https://stacksnippets.net/js :(
What am I missing to make things work?
placing Qqq code inside SimpleManu is causing Qqq to remount on every SimpleMenu render.
Because Qqq remounted, the anchorEl reference is no longer valid.
To fix that, move Qqq outside SimpleMenu.
const Qqq = (props) => {
return (
<Button
aria-controls="simple-menu"
aria-haspopup="true"
onClick={props.handleClick}
>
Broken Menu
</Button>
)
}
export default function SimpleMenu() {
const [anchorEl, setAnchorEl] = React.useState(null);
const handleClick = event => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
return (
<div>
<p> hello</p>
<Button
aria-controls="simple-menu"
aria-haspopup="true"
onClick={handleClick}
>
Open Menu
</Button>
<Qqq handleClick={handleClick}/>
<Menu
id="simple-menu"
anchorEl={anchorEl}
keepMounted
open={Boolean(anchorEl)}
onClose={handleClose}
>
<MenuItem onClick={handleClose}>Profile</MenuItem>
<MenuItem onClick={handleClose}>My account</MenuItem>
<MenuItem onClick={handleClose}>Logout</MenuItem>
</Menu>
</div>
);
}
Code Sandbox
To see that Qqq really re mounts on every SimpleMenu render, go to the Code Sandbox and move Qqq to be inside SimpleMenu like before.
useEffect will print to console on every mount, and you can see what happens.
I am using redux-form in order to submit a new user signup page in my React Web App, but when I try to grab the input field values on the form of the parameter values, it comes back undefined in mapDispatchToProps. I have read many posts of people claiming their values variable comes back undefined, but that is not the case for me. Only when I console.log(values.[inputName]) do I get undefined. According to the documentation, I cannot tell that I am doing anything incorrectly.
Can someone please help determine what is causing values.email to be undefined? Thanks.
// presentational component
class Signup extends Component {
render() {
const { handleSubmit } = this.props;
return (
<div>
<h1>Signup</h1>
<form onSubmit={handleSubmit}>
<div>
<label>
Email:
<Field component="input" type="email" name="email" />
</label>
</div>
<div>
<label>
Password:
<Field component="input" type="password" name="password" />
</label>
</div>
<button type="submit" >Submit</button>
</form>
</div>
)
}
}
export default reduxForm({
form: 'Signup',
enableReinitialize: true
})(Signup)
// redux container component
const mapDispatchToProps = (dispatch) => {
return {
handleSubmit: (values) => {
console.log(values.email); // outputs undefined!
}
};
}
const SignupContainer = connect(
null,
mapDispatchToProps
)(Signup)
export default SignupContainer;
// reducer index.js
import { reducer as formReducer } from 'redux-form';
export const appReducer = combineReducers({
form: formReducer
})
// store.js
export const store = createStore(
appReducer,
applyMiddleware(
thunkMiddleware,
loggerMiddleware
)
);
Side Note
I have noticed that whenever I first click the submit button on the form, the page refreshes (so I do not see the console.log). All proceeding times does not cause a refresh, but I am unsure as to why. Any explanation of this would be greatly appreciated, too.
Update
After changing my Router from HashHistory to BrowserRouter (react-router), the page refreshes every time I click submit. Seems that I have two problems now.
I'm very new to React and ES6. I'm building a small application using React and I'm following ES6 standard. Now I need to open a modal window on a button click.
I tried react-bootstrap modal and skylight. But did not find much luck.
Can anyone suggest the best way of opening/closing modal along with a callback.
Thanks in advance.
I've put together an example to illustrate how you might go about this, making use of the parent/child relationship and passing down a callback.
The scenario is basically:
There is a parent <App /> component
It can show a <Modal /> component
<App /> controls whether the <Modal /> is open or not
<App /> passes its child, <Modal />, a callback to "closeModal"
See this JSBin example for the full solution in action: http://jsbin.com/cokola/edit?js,output
And a visual summary:
<Modal /> is just a "dumb" component. It does not "control" whether it is open or not. This is up to the parent <App />. The parent informs it of how to close itself via passing down a callback this.props.closeModal
class Modal extends React.Component {
render() {
const { closeModal } = this.props;
return (
<div className="jumbotron" style={{position: 'absolute', width: '100%', top: 0, height: 500}}>
<h1>Some Modal</h1>
<button
className="btn btn-md btn-primary"
onClick={closeModal}
>Close Modal</button>
</div>
)
}
}
<App /> is aware of the open/closed state and controls its child, <Modal />
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
modalOpen: false
};
}
_openModal() {
this.setState({modalOpen: true});
}
_closeModal() {
this.setState({modalOpen: false});
}
render() {
const { modalOpen } = this.state;
return (
<div>
<button
className="btn btn-md btn-primary"
onClick={this._openModal.bind(this)}
>Open Modal</button>
{/* Only show Modal when "this.state.modalOpen === true" */}
{modalOpen
? <Modal closeModal={this._closeModal.bind(this)} />
: ''}
</div>
);
}
}