I have a simple React Select as content prop in a Semantic UI React Popover component. I am constrained by each of the package versions inside the project (available in the following codesandbox https://codesandbox.io/s/wy194rz908):
React: ~15.5.0
ReactDOM: ~15.5.0
React-Select: ^2.1.1
Semantic UI React: 0.71.5
As you can see, the React Select options closes when a selection is done.
On the other hand, I found that updating React, React-DOM and SemanticUI to their latest versions make the feature work. As you can see, the selection is done and the Select options do not fold (available in the following codesandbox https://codesandbox.io/s/6y14qyykk3).
As I can not update update the React and SUIR, what workaround should I follow in order to make this work?
Thanks!
You have to use a Controlled Popup Component, as stated in docs:
import React from 'react'
import { Button, Popup } from 'semantic-ui-react'
class PopupExampleContextControlled extends React.Component {
state = {}
toggle = () => this.setState({ open: !this.state.open })
handleRef = node => this.setState({ node })
render() {
const { node, open } = this.state
return (
<div>
<Button content='Open controlled Popup' onClick={this.toggle} />
<Popup context={node} content='Hello' position='top center' open={open} />
---------->
<strong ref={this.handleRef}>here</strong>
</div>
)
}
}
export default PopupExampleContextControlled
In this way you can control when popup opens and closes.
I am controlling the Popup using the open prop available through its props api. I change its state from true to false when clicking the caret down icon button.
Solution: https://codesandbox.io/s/rmoxx98qkn
Related
I am going through a React Learning Textbook that is explaining me about Hooks. The hooks part is working fine.
The author is illustrating how to customize Hooks with some easy to use style and related components.
I have the following code.
import React from 'react';
// import logo from './logo.svg';
import './App.css';
import StarRating from './components/StarRating';
import StarRating2 from './components/StarRating2';
import Headline from './components/Headline';
function App() {
return (
<article>
<Headline/>
<StarRating/>
<StarRating2
style={{ backgroundColor: "blue" }}
onClick={e => alert(" click")}
/>
</article>
);
}
export default App;
The component code is like this.
import { useState } from "react";
import React from "react";
import { FaStar } from "react-icons/fa";
const createArray = length => [...Array(length)];
const Star = ({ selected = false, onSelect = f => f }) => (
<FaStar color={selected ? "red" : "grey"} onClick={onSelect} />
);
const numberOfStarts = 10;
const numberDefaultState = 7;
function StarRating2({ totalStars = numberOfStarts })
{
//will hold the user’s rating
// create this variable by adding the useState hook directly to the StarRating component:
const [selectedStars, setSelectedStars] = useState(numberDefaultState);
return (
<>
<p>
This is Star Rating 2 - and it has some imporvements
</p>
{createArray(totalStars).map((n, i) => (
<Star
key={i}
selected={selectedStars > i}
onSelect= {
() => {
setSelectedStars(i + 1);
}
}
/>
))}
<p>
{selectedStars} of {totalStars} stars
</p>
</>
);
}
export default StarRating2;
Unfortunately, neither does the component display change its back ground color. Nor does it respond to a click. The app continues to run with no errors or anything. and I can see that the style properties set are visible in the component tree in the react developer tools in Firefox. So, the code is reflecting on the app for sure.
I am in the 6th chapter now, and so far, every chapter code has worked exactly as it is in the book. This one though, is not. I am unsure if this a wrong code (and perhaps, I should reach out to the author) or this is something that is no longer allowed and the book is simply out of date.
StarRating2 is a React component, you are passing couple of props to StarRating2 but you aren't using those props inside StarRating2 component. CSS styles and event handlers work on native DOM elements.
What you need to do is make use of the props that are passed to StarRating2 in from App component. You can apply the styles prop on the wrapper element that wraps all the JSX code of StarRating2 component and use onClick prop on the element which should react to the click event in some way.
To apply the background color in StarRating2 component, wrap the JSX code in a wrapper element, for example a div and then use the value of style prop on this wrapper element.
function StarRating2({ totalStars = numberOfStarts, style }) {
...
return (
<div style={style}>
...
</div>
);
}
To use the click handler, you will need to use the onClick prop and add it on any native DOM element.
You need to spread the props from the parent to a native react component , styles and eventListeners can only be attached to native components like div , button etc , if the Star component supports adding color and eventListeners through its , you can do ... rest in props and spread it to star component , if you need any help , send me a codesandbox , I will explain in that
I am trying to use Material UI components in NextJS but they are not working properly.
import React, { Component } from "react";
// MATERIAL
import Snackbar from "#material-ui/core/Snackbar";
import MuiAlert from "#material-ui/lab/Alert";
export default class NewProduct extends Component {
constructor() {
super();
this.state = {
testSnack: false,
};
}
testSnackbars = () => {
this.setState({ testSnack: true });
};
render(){
return{
<>
<Snackbar
open={this.state.testSnack}
autoHideDuration={5000}
onClose={this.handleClose}
>
<MuiAlert
elevation={6}
variant="filled"
onClose={this.handleClose}
severity="success"
>
Product Added!
</MuiAlert>
</Snackbar>
<button onClick={this.testSnackbars}>
Save
</button>
</>
}
}
}
This is a simple logic for showing snackbar on button click but this doesnt seem to work in NextJs, I use Material in ReactJs very often and this never happened there. Can someone tell me what I'm doing wrong here?
I am not able to run snackbars using my state. If I pass in open={true} property, it shows up but not working through state variable.
Replace this line
return {...};
with
return (...);
Besides that, everything seems to look good on my codesandbox.
Since upgrade material-ui to v4, I got some warnings with Modal component.
E.g
Failed prop type: Invalid prop children supplied to ForwardRef(Modal).
Function components cannot be given refs.
This is Modal code (warning 1):
import React from 'react';
import Proptypes from 'prop-types';
...
class DetailDialog extends React.Component {
render() {
const { classes, open, onClose } = this.props;
return (
<Dialog
open={open}
>
...
</Dialog>
);
}
}
DetailDialog.propTypes = {
open: Proptypes.bool,
onClose: Proptypes.func,
};
export default DetailDialog;
This is Modal code (warning 2):
import React from 'react';
import PropTypes from 'prop-types';
...
class SelectCatDialog extends React.Component {
render() {
const { open, list, onClose } = this.props;
return (
<Dialog
open={open}
onClose={onClose}
>
...
</Dialog>
)
}
}
SelectCatDialog.propTypes = {
open: PropTypes.bool,
onClose: PropTypes.func,
}
SelectCatDialog.defaultProps = {
list: [],
}
export default SelectCatDialog;
This is call Modal page code:
import React from 'react';
import DetailDialog from './components/DetailDialog';
import SelectProcDialog from './components/SelectProcDialog';
class Index extends React.Component {
render() {
return (
...
<DetailDialog
open={this.state.detailDialog}
entity={this.state.currentDetail}
onClose={this.handleDetailClose.bind(this)}
/>
<SelectProcDialog
open={this.state.catalogDialog}
list={this.props.catalog}
onOk={(value) => this.handleSelectCatalogOk(value)}
onClose={() => this.setState({ catalogDialog: false })}
/>
...
)
}
}
export default Index;
What happened? Working fine in v3 version. Can someone answer?
Since V4, Dialog and Modal children must be able to hold a ref.
The following can hold a ref:
Any Material-UI component
class components i.e. React.Component or React.PureComponent
DOM (or host) components e.g. div or button
React.forwardRef components
React.lazy components
React.memo components
The error declares that you provide function component as a child to modal.
To fix the error, change the function component to something that can hold a ref (e.g class component).
I just faced the exact same issue after migrating from Material-UI v3 to v4.
I totally agree with the accepted answer, nevertheless, I post here another approach, in the case someone would rather keep using a functional component (as I did).
Functional components can't hold a ref as is.
So the way of providing a ref to a child component is actually to forward it.
The React documentation has a well explained example about this, and this issue on the ReactJS Github details it a bit more.
So basically, what could be done here is :
const Transition = React.forwardRef((props, ref) => (
<Slide direction="up" {...props} ref={ref} />
));
to be able to forward the ref through the Transition component, down to the Slide component.
Typescript way
⚠️ Be aware that the previous code will throw a TS2322 error if used in a Typescript project.
This error is described and solved in this Material-UI Github issue.
So, in a Typescript project, the best way (imho) to use a functional component as Transition component for a Material-UI v4 Dialog component, is the following :
import { SlideProps } from '#material-ui/core/Slide';
const Transition = React.forwardRef<unknown, SlideProps>((props, ref) => (
<Slide direction="up" {...props} ref={ref} />
));
And the code above fixes both errors :
Failed prop type: Invalid prop children supplied to ForwardRef(Modal).
[TypeScript] Error: TransitionComponent type not assignable to 'ForwardRefExoticComponent'
In my react application, when I click on an external link suppose http://www.example.com/about, I do not want it to redirect to that website but I want that about page to render as a popup in my react application. How can I approach this?
You might make a wrapper component for the links that would check if the href prop matches your website location or goes to a 3rd party site, and renders either a normal a tag or a modal dialog with an iframe inside.
Eg. Link.js
import React, { Component, Fragment } from 'react'
import Modal from '...' // any of the available modal component for react
export default class Link extends Component {
state = { isOpen: false }
render () {
const url = new URL(this.props.href)
if (url.hostname === WEBSITE_HOSTNAME) return (
<a href={this.props.href}>{this.props.children}</a>
)
return (
<Fragment>
// you could also use an <a> here if you want users to be able to open the link in a new tab with a right click
<button onClick={() => this.setState({ modalOpen: true })}>{this.props.children}</button>
<Modal isOpen={this.state.isOpen}>
<iframe src={this.props.href} />
</Modal>
</Fragment>
)
}
}
Even better, split it into two components as there's no need for regular links to have any state...
The problem is I have a form whit three states: default, error and success. Depending on the state, a specific component is rendered into the dom.
I need to add a fade in out animation when this component enters or leave.
I've tried whith custom CSS, GSAP ( but don't want to install more packages to my project ) and now trying with react-transition-group.
To keep is simple I've created the "error" component as follow:
export default class NewsletterFormError extends React.Component {
componentWillMount() {
}
componentDidMount() {
}
render() {
return (
<div className="NewsletterFormError">
I'm an error message
<style jsx>{`
.NewsletterFormError {
font-size: 50px;
}
`}</style>
</div>
)
}
}
And on the index page I have:
{ this.state.formError &&
<CSSTransitionGroup
transitionName="test"
transitionAppear={true}
transitionAppearTimeout={200}
transitionEnter={true}
transitionEnterTimeout={2000}
transitionLeave={true}
transitionLeaveTimeout={2000}>
<NewsletterFormError />
</CSSTransitionGroup>
}
For some reson, when this.state.formError is true, the component renders and the fade in is done, but when the state chages to false, the fade out is not working.
Unfortunately, pure React CSS Transition groups can't trigger an animation when a component is unmounted. See this github issue for more details. This repo with a comparison of animation methods in react may be helpful, they recommend using React CSS Transition groups in conjunction with GSAP or Anime.js