i have redux form inside my reactstrap modal.when my popup appear,console log show below warning.without Form it's working charm.
You have a component say it's name is CustomComponent that retuns something like this
<div>
<Form {...this.props}>
<p> this.props.pText </p>
<Button>I'm a button named {this.props.buttonName} </Button>
</Form>
</div>
and when you render it in another file you do this
<CustomComponent pText="hi" buttonName="randomName">
so what happens is you are passing the buttomName, pText to your Form which doesn't accept pText, buttonName (remember, Your button & accept those props but not the form itself, so the virtual react DOM guesses that the prop is not for react, so it must be a real DOM prop & doesn't know what to do with it, to solve the problem, simply remove the {...this.props}
this is a result of how React is handling custom vs predefined DOM attributes -> see here
https://reactjs.org/warnings/unknown-prop.html
Related
I have component with navigation, on click item to child component passed in props some params, one of params - object 'itemImage' with className and url, like this:
{
url: '/static/image.svg',
className: 'absolute hidden md:block min-w-53 lg:min-w-68 mt-30 lg:mt-19 -ml-28 lg:-ml-75',
}
In child component ItemComponent:
{
itemImage &&
<img className={itemImage.className} src={itemImage.url} alt='' />
}
ItemComponent is selected from an array according to the order of the element in navigation (it is responsible for the object passed to the child component), since the list of navigation elements and elements of the array of pictures are not related and of different lengths. The sample is implemented on the basis of an index in map for objects and an index in an array with pictures, to be more precise.
Problem:
the pictures flicker as the state of the parent and the child is updated, is it possible to somehow avoid this and make the change of the picture clear without the flickering of the previous card.
You can use the below-mentioned code to render the Array of Images.
<>
{this.props.Images.map(item=>{
return (item)
})}
<p>
{JSON.stringify(this.state)}
</p>
<p>
{JSON.stringify(this.props.changed)}
</p>
<button onClick={this.props.onChange}>Change</button>
<button onClick={this.onCurrentChange}>Current State Change</button>
</>
Please check the demo here Demo
You can make somethings to try to prevent that.
1- Add a key prop to the elements. It help react understand that it is the same data from before and not re-render that piece.
2- Use react PureComponent on the flickering element https://reactjs.org/docs/react-api.html#reactpurecomponent to prevent the re-render
3 - Instead of purecomponent implement shouldComponentUpdate
So, I'm trying to use Semantic UI modal component with the form component.
My problem is that if I use these two together the UI becomes bad.
I created a sandbox about my current situation: https://codesandbox.io/s/2n1pj96ry
As you can see now the submit button does not attached to the form.
If I move the Form component directly inside the Modal component, like this:
<Modal...>
<Form>
...
</Form>
</Modal>
the submit will attached to the form, but the UI breakes down.
I tried to add different classes to these components (like ui modal to the Form component, but it doesnt worked well).
Do you have any suggetsion?
Thanks for you help!
You can use the as prop on the Modal to make it a form element.
<Modal
as={Form}
onSubmit={e => handleSubmit(e)}
open={true}
size="tiny">
Any button with the submit type in your modal will fire the onSubmit handler. I find this to be a nice way to opt-in to required fields and easy validation by the browser on form elements.
Be sure to pass the event to your submit handler and use the preventDefault method to avoid the browser from automatically trying to post your form.
Forked your sandbox and made a working example. The modal is changed to a <form> element, the Input has the required property and the browser will demand the element is valid before firing the onSubmit handler. The default form action is prevented, and you can handle as desired with whatever.
I have been trying to fire an onClick on a react component. The event fires if I use
<button onClick={()=>this.goToPage('next')}>Next Page</button>
If I use the same method on a stateless component, it doesn't fire:
<PageButton onClick={()=>this.goToPage('next')}>Next Page</PageButton>
Why this is not possible?
Because what you are defining is a custom component. Note, that everything that you provide to the custom component is considered as props. So, your onClick method is also provided as props. Essentially you'll be required to do -
<PageButton onClick={()=>this.goToPage('next')}>Next Page</PageButton>
and in your <PageButton /> component -
<button onClick={this.props.onClick}>Next Page</button>
if you know what props you are providing to this component and not providing any unnecessary props, you can even spread the props object, like -
<button {...this.props}>Next Page</button>
Note - If you have other props to provide to this component as well, kindly refrain from using this method, as this will result in many unrecognized function warnings.
PS: Even if you write
<PageButton style={{backgroundColor: 'red}}>Next Page</PageButton>
it won't work because, this is treated as a prop. You'll need to handle the style prop in the render method of this <PageButton/> component
This does not work on a stateless component because the onClick is considered as a prop rather a event listener , you should implement.
For example inside PageButton you should implement something like this
render(){
return <div onClick={()=>this.props.onClick('next')}/>
}
For my React component I have the following:
const ArchiveButton = ({collection, onClick}) => {
return (
<span>
{ collection.archived &&
<Button bsStyle="link" onClick={onClick}><i className="fa fa-rotate-left" /> Unarchive</Button>
}
{ !collection.archived &&
<Button bsStyle="link" onClick={onClick}><i className="fa fa-archive" /> Archive</Button>
}
</span>
);
};
I'm attempting to test by passing in different values for collection.archived and I want to check for the existence of the text "Unarchive" vs "Archive". When I do a wrapper.find('Button') and try and check against .text() it is just <Button /> and the only way I've figured out how to test it is:
const wrapper = shallow(<ArchiveButton onClick={onClick} {...props}/>);
let button = wrapper.find('Button').prop('children');
expect(button[1]).toMatch(/\sUnarchive/);
Seems a bit off though, not sure. Thanks!
It's because you're using shallow rendering, so your nested Button component doesn't get rendered. As you've seen, you can access the nested component props to test the values you pass to it.
If you prefer to have the button content rendered, use normal rendering instead.
Note that the nested Button is not a normal DOM element, which would be rendered anyway even if you use shallow rendering, but it's instead a component itself.
If you think about it, if you don't use shallow rendering in your case, you're not really unit-testing your component, as you're also asserting something about the Button component. If you use shallow rendering and access the props of the nested component, you're really just testing that your code is calling the Button component with the correct arguments, and you're not making any assumptions as how the Button component will render.
This is normally what you want to do in a unit test.
I am trying to get a form working inside of a Material UI Dialog component. If I wrap the Dialog in the form tags, they do not even show up in the resulting html (no idea why yet)...
<form onSubmit={someFunction}>
<Dialog>
...
</Dialog>
</form>
If I reverse it and put the form tags inside the Dialog, the form elements show up in the resulting html, but then the action button set to type="submit" will not fire the form's onSubmit.
<Dialog>
<form onSubmit={someFunction}>
...
</form>
</Dialog>
Has anyone had any success getting this combination to work? I know I can just call the function directly from the action button click, but I am also using Redux Form and have other non-dialog forms in the app, so I have it bound to the form element. So I really need to invoke the form submit from a Dialog somehow.
Actually - I have/had the onSubmit={handleSubmit(this.myFunction)} to begin with and that was not the issue. The issue turned out to be how Material UI mounts the Dialog (which apparently is different than react-toolbox). They mount it on the body - I assume for easier positioning - so anything outside of the Dialog is ignored.
With the form inside the Dialog, the buttons are outside the form (which is again apparently different than react-toolbox). So to make it work, you have to use the HTML 5 'form' attribute as detailed here (along with a poly-fill for older browsers if needed). The form needs an id attribute and then the button outside it needs a form attribute with the value set to the id of the form. Then the form elements inside the dialog behave as expected. Thanks for the response though!
The material-ui Dialog component inherits from the material-ui Modal component, which means it accepts the prop "disablePortal" - which is false by default.
from the docs:
"Disable the portal behavior. The children stay within it's parent DOM hierarchy."
https://material-ui.com/api/modal/#props
by default, the dialog is rendered as a child of your root html node, to have it render inside the <form> tag, you need to disable the portal behavior.
<form onSubmit={someFunction}>
<Dialog disablePortal>
<DialogTitle>
title!
</DialogTitle>
<DialogContent>
form fields go here
</DialogContent>
<DialogActions>
<button type="submit">submit!</button>
</DialogActions>
</Dialog>
</form>
<form onSubmit={someFunction}>
<Dialog disablePortal>
<DialogTitle>
title!
</DialogTitle>
<DialogContent>
form fields go here
</DialogContent>
<DialogActions>
<button type="submit">submit!</button>
</DialogActions>
</Dialog>
</form>
Hey yeah I have this combo working... well I am using the Dialog component from react-toolbox which is very similar to Material-ui but they use Css-modules for styles instead of inline.
So the function you provide to the onSubmit attribute of the form element is going to be the handleSubmit function from redux-form. If you want to do anything such as dispatch actions and store the data then you will need to pass in an onSubmit function to the handleSubmit function. What happens is your onSubmit function is called with the values(object with properties of the values of your form) and the dispatch function from the redux store. You can see the project I have which has the setup you are looking for.
Instead of onSubmit={someFunction}, make it
<Dialog>
<form onSubmit={this.someFunction}>
...
</form>
</Dialog>