I am using React Container Pattern for a project with Formik. If I want to pass some props from "Container component" to "Presentational component" how can I catch those props in Presentational Component?
//CONTAINER COMPONENT
render() {
return (
<CreateColorContainer
key="CreateColor"
name="Add Color"
{...this.state}
/>
);
}
//PRESENTATIONAL COMPONENT
<Formik
initialValues={}
validationSchema={}
onSubmit={(fields) => {}}
>
{(props) => {
const { touched, errors, setFieldValue } = props;
return (
<div className="page-wrapper">
//Props i want to use here
</div>
);
}}
</Formik>
Related
<SimpleDialog
selectedValue={selectedValue}
open={open}
onClose={handleClose}
title={title}
componentBody={componentBody}
/>
I would like to pass the '' handleclose '' to the component (componentBody), but that component comes to me as '' props '', is there a way to do that?
If you want to pass a component to another component you should use high order components or HOC, and wrap children components like layouts, like below:
function App() {
return (
<div className='App'>
<HOC message={"from App"}>
<ComponentB name='Reza' func={() => alert("alert message")} />
</HOC>
</div>
);
}
const ComponentB = ({ name, func }) => {
return <h1 onClick={func}>name is : {name}</h1>;
};
const HOC = ({ children, message }) => {
return (
<>
{message}
<br />
{children}
</>
);
};
export default App;
In your codebase you can do it like below:
<SimpleDialog
selectedValue={selectedValue}
open={open}
title={title}
>
<componentBody onClose={handleClose}/>
</SimpleDialog>
I am building a package to generate forms. It exports a component that takes a schema to create the form fields. I am using Formik to manage the form state.
I want to get access to the form state from the parent/consuming component but I don't know how to go about it.
Stripped out code sample:
// Child/consumable component
import { Formik, Form as FormikForm } from "formik";
export function DynamicForm(props) {
return (
<Formik {...props}>
<FormikForm
className="needs-validation"
noValidate=""
onChange={props.handleChange}
>
{/* a loop to generate the form fields using the schema */}
{props.children}
</FormikForm>
</Formik>
);
}
// Parent component
import { DynamicForm } from '....';
// >>> I would like to have a variable here that contains the form's state <<<
export const App = () => {
return (
<div className="App">
<DynamicForm
enableReinitialize
validationSchema={validationSchema}
onSubmit={onSubmit}
formSchema={formSchema}
handleChange={(e) => console.log(e.target.name, e.target.value)}
>
<button type="submit">Submit</button>
</DynamicForm>
</div>
);
};
Thank you
In a project I am working on Unit test with Jest and enzyme. My component is a styled component that wraps around another component. My CvvFieldUi component uses TextField component of material UI. Here is my code
export class CvvFieldUI extends CvvFieldState {
render() {
const { classes } = this.props;
return (
<TextField
fullWidth
type={!this.state.showCvv ? "password" : "text"}
id="cvv-number"
placeholder={this.state.placeHolder}
value={this.state.cvvValue}
className={clsx(classes.textField)}
onChange={(event) => {
this.handleChange(event);
this.props.CVV(this.state.cvvValue);
}}
InputProps={{
classes: { root: classes.inputField },
endAdornment: (
<InputAdornment position="end">
<IconButton
aria-label="toggle password visibility"
onClick={(event) => this.handleClickShowPassword(event)}
onMouseDown={(event) => this.handleMouseDownPassword(event)}
>
{this.state.showCvv ? <Visibility /> : <VisibilityOff />}
</IconButton>
</InputAdornment>
),
}}
variant="outlined"
/>
);
}
}
CvvFieldUI.propTypes = {
classes: PropTypes.object.isRequired,
};
export default withStyles(styles)(CvvFieldUI);
I want to test the state of this component. Here is my code.
test('Testing CVV Field', () => {
/*const { getByText } = render(<App />);
const linkElement = getByText(/learn react/i);
expect(linkElement).toBeInTheDocument();*/
const wrapper = shallow(
<MuiThemeProvider theme={theme}>
<CvvFieldUI placeHolder="placeholder" CVV={()=>{}} />
</MuiThemeProvider>
).dive();
const input = wrapper.find(OriginalCvvField);
console.log("Child",input.state().cvvValue.length);
});
What I have done is to get the unwrapped component from the styledcomponent. But when i do this it gives me error
ShallowWrapper::state() can only be called on the root
It looks like I am unable to get unstyled component.
Question:
How can I call state method on the component?
UPDATE:
Now I am testing visible out put but it is also not working. It does show me the inputand its properties correctly but I am unable to manipulate it. When I display the value of input, it still shows null. Here is my code
const wrapper = mount(
<MuiThemeProvider theme={theme}>
<CvvFieldUI placeHolder="placeholder" CVV={()=>{}} />
</MuiThemeProvider>
);
const Cvv=wrapper.find(OriginalCvvField);
const input = Cvv.find('input');
input.simulate('focus');
input.simulate('change', { target: { value: 'Changed' } });
console.log("Input tag",input.get(0));
I have a stateless component and i want to be able to click on the image and redirect it to a new page.
The issue that i am having is that i cannot get onClick to work correctly.
I was trying to write a function within the onClick = {this.ProjectSelected} but this will not work.
Do i have to pass a function (onClick) from the parent to child component? If so how do i do that?
I am able to log the project id to the console.
Thanks for the help.
const projectListTemplates = (props) => {
const { classes } = props;
return (
<div>
<div className={classes.root}>
<GridList className={classes.gridList}>
<GridListTile key="Subheader" cols={2} style={{ height: 'auto' }}>
<Subheader component="div">Projects</Subheader>
</GridListTile>
{props.data.map(item => (
<GridListTile key={item.image}>
<img src="./images/Project/1.jpg" alt={item.title} />
<GridListTileBar
title={item.title}
subtitle={<span> {item.name}</span>}
onClick={()=>console.log(`this project was clicked ${item.id}`)}
>
</GridListTileBar>
/>
<ProgressBar now={60} />
</GridListTile>
))}
</GridList>
</div>
</div>
);
In stateless component we are not defining any local property like state or methods. We have only props and rendering data based on props. We have only props events to trigger. So we have to pass a event function from parent component in order to handle click event. If you want to keep click event locally, convert component to stateful (Class).
Stateless
const ProjectListComponent = (props) => {
const { onClick } = props
return (
<button onClick={onClick}>Click me</button>
)
}
class AppComponent extends Component {
handleClick() {
console.log('clicked')
}
render() {
return (
<ProjectListComponent onClick={this.handleClick} />
)
}
}
Stateful
class ProjectListComponent extends Component {
handleClick() {
console.log('clicked')
}
render() {
return (
<button onClick={this.handleClick}>Click me</button>
)
}
}
In my app.js, I have this
render() {
return (
<div id="App">
<SearchBar />
</div>
);
}
And inside of SearchBar, I import react-autosuggest and have this -
render() {
const { value, suggestions } = this.state;
const inputProps = {
placeholder: "Search",
value,
onChange: this.onChange
};
return (
<Autosuggest
style={style}
suggestions={suggestions}
onSuggestionsFetchRequested={this.onSuggestionsFetchRequested}
onSuggestionsClearRequested={this.onSuggestionsClearRequested}
getSuggestionValue={getSuggestionValue}
renderSuggestion={renderSuggestion}
inputProps={inputProps}
onSubmit={this.doSomething}
/>
);
}
Where all these functions are standard boilerplate functions that react-autosuggest uses. How do I access what was searched for inside of SearchBar inside of it's parent, app.js?
You can use props to raise the data from the Autosuggest events to the parent component. Create a method inside App and pass it down as a prop to the SearchBar component. Then, call it with the Autosuggest event.
App
class App extends React.Component {
onSubmit(e) {
// `e` is the data that was passed through from the `Autosuggest` event.
console.log(e);
}
render() {
return (
<div id="App">
<SearchBar onSubmit={this.onSubmit} />
</div>
);
}
}
SearchBar
<Autosuggest onClick={this.props.onSubmit} />
You can use a callback function at the SearchBar component. Follow the steps below according to your use case:
Add below function at SearchBar component
onHandleChange(event, value){
this.setState({ value });
this.props.getInputData(event, value);
}
Use above function at AutoSuggest component
return (
<Autosuggest
...
onChange={(event, value) => this.onHandleChange(event, value)}
...
/>
);
Use SearchBar component like
render() {
return (
<div id="App">
<SearchBar getInputData={(event, value) => this.getAutosuggestInput(event, value)}/>
</div>
);
}
Here you get the value of input box at the parent component
getAutosuggestInput = (event, value) => {
//add your logic here
}