'react-bootstrap' does not contain an export named 'Card' - reactjs

I am building a React app with the new react-bootstrap v1 (where Bootstrap 3 for React has changed to no longer include the Panel component - it is now instead replaced with the Card component). I installed the npm install which is: npm install react-bootstrap bootstrap
But when I go to run the application it tells me: 'react-bootstrap' does not contain an export named 'Card'. Here is what my component looks like:
import React, { Component } from 'react';
import mealsCall from '../DBRequests/mealCalls';
import { Card, Button } from 'react-bootstrap';
export class Meals extends Component {
state = {
meals: [],
}
componentDidMount() {
mealsCall
.getMeals()
.then((meals) => {
this.setState({ meals })
})
.catch((error) => {
console.error('error with GET meals call', error);
});
};
render() {
const meals = this.state.meals.map((meal) => {
return (
<div key={meal.id}>
<Card style={{ width: '18rem' }}>
<Card.Img variant="top" src="holder.js/100px180" />
<Card.Body>
<Card.Title>{meal.mealName}</Card.Title>
<Card.Text>
<h3>{meal.restaurantName}</h3>
<h4>{meal.city}, {meal.state}</h4>
</Card.Text>
<Button variant="primary">View Meal</Button>
</Card.Body>
</Card>
</div>
);
})
return (
<div>
{meals}
</div>
);
}
}

From react-bootstrap version 1.0.0-beta.x:
The correct import statement for Card is
import Card from "react-bootstrap/Card";
The correct import statement for Button is
import Button from "react-bootstrap/Button";

Related

How to scroll to bottom of div

I have troubles with scrolling down my component. I want scroll bar thumb to be at the very end of chat div from the start. I am not sure what the probleme is here. MessageTo and MessageFrom are components that represent paragraphs with text and display author's name. ChatInput is textarea with send button.
import React from 'react';
import './index.css';
import MessageFrom from './message-from';
import MessageTo from './message-to';
import ChatInput from './chat-input';
import SimpleBarReact from 'simplebar-react';
import 'simplebar/src/simplebar.css';
class Chat extends React.Component {
componentDidMount() {
this.scrollToBottom();
}
componentDidUpdate(){
this.scrollToBottom()
}
scrollToBottom = () => {
this.el.scrollIntoView({behavior:"smooth"});
}
render(){
return(
<div className="chat" id="slider-container">
<SimpleBarReact style={{maxHeight: 680}} id="scroll-bar-cont">
<div className="messages-container" id="for-slider" >
<MessageFrom />
<MessageTo />
<div style={{ float:"left", clear: "both" }}
ref={el => {this.el=el;}}>
</div>
</div>
</SimpleBarReact>
<ChatInput />
</div>
);
}
}
export default Chat;
https://codesandbox.io/s/great-currying-x4m8m?file=/src/message-to.js
It works well. But It doesn't work in next level component.

How do I change the attributes of a dependencies?

So I am trying to learn how to use the npm library, and I found this carousel. I implemented it into my project, but I am unsure about how to change the attributes. Here is the doc: https://www.npmjs.com/package/react-responsive-carousel
and here is my current code:
import React, { Component } from 'react';
import "react-responsive-carousel/lib/styles/carousel.min.css";
import { Carousel } from 'react-responsive-carousel';
import Project1 from './Project1'
import Project2 from './Project2'
class Projects extends Component {
constructor(props){
super(props)
this.state = {
showArrows: 'false',
showIndicators: 'false'
}
}
render() {
const styles = {
display: 'none'
}
return (
<Carousel>
<div>
<Project1 />
</div>
<div>
<img style = {styles}src="http://lorempixel.com/output/cats-q-c-640-480-1.jpg" />
<Project2 />
</div>
</Carousel>
);
}
};
export default Projects
You can do it as you will do for normal components.
<Carousel showArrows={false} showIndicators={false}>
Refer for demos.

withStyles component wrap

I have a following component:
import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } from '#material-ui/core/styles';
import SnackbarContent from '#material-ui/core/SnackbarContent';
import Snackbar from '#material-ui/core/Snackbar';
const styles = theme => ({
error: {
backgroundColor: theme.palette.error.dark,
}
})
class Snack extends React.Component {
state = {
opendialog: false,
}
constructor(props) {
super(props);
}
test() {
this.setState({opendialog: !this.state.opendialog});
}
render() {
return (
<Snackbar open={this.state.opendialog}>
<SnackbarContent message="test"/>
</Snackbar>
);
}
}
export default withStyles(styles)(Snack);
and app main:
import React, { Component } from 'react';
import Button from '#material-ui/core/Button';
import logo from './logo.svg';
import './App.css';
import Snack from './Snack.js';
class App extends Component {
constructor(props) {
super(props);
this.snack = React.createRef();
}
render() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h1 className="App-title">Welcome to React</h1>
</header>
<p className="App-intro">
To get started, edit <code>src/App.js</code> and save to reload.
</p>
<Button variant="contained" color="primary" onClick={this.handleHello}>Hello World</Button>
<div>
<Snack ref={ ref => this.snack = ref } />
</div>
</div>
);
}
handleHello = () => {
this.snack.test();
}
}
export default App;
I get a "TypeError: _this.snack.test is not a function" when I click the button, however if I drop the withStyles the code works correctly.
I'm just replacing "export default withStyles(styles)(Snack);" line with "export default (Snack);".
Why it does not work correctly with the "withStyles"? How can I make it work?
Because withStyles wraps your component, you need to instead use:
<Snack innerRef={ref => (this.snack = ref)} />
withStyles passes the innerRef property to the wrapped component as ref.
I tried this using the latest version of #material-ui/core (currently 3.8.1). I can't guarantee that older versions support this in the same way.
Here's a fully working example:
The problem is because the withStyles HOC return a new component so you are getting the reference of the HOC. You can use innerRef prop:
<Snack innerRef={ ref => this.snack = ref } />
According to the official documentation:
It adds an innerRef property so you can get a reference to the wrapped component. The usage of innerRef is identical to ref.
You can check it in the official documentation here withStyle function.
I already tested it with your current version it works properly

In react how do I get a modal to display in one component by clicking an icon in another?

I am using material UI with React. I have a modal component and a ButtonAppBar. Inside the ButtonAppBar there is a shopping cart icon that I added. I am still a bit new to React and would like to know the best way to display the modal when the shopping cart is clicked. Thanks in advance.
So here is my App.js:
import React, { Component } from 'react';
import { BrowserRouter } from 'react-router-dom';
import { Route } from 'react-router-dom';
import './App.css';
import ShopHome from './containers/ShopHome';
import ButtonAppBar from './components/ButtonAppBar';
import SimpleModalWrapped from './containers/ShoppingCartModal';
class App extends Component {
handle
render() {
return (
<BrowserRouter>
<div>
<ButtonAppBar />
<SimpleModalWrapped />
<Route exact path="/" component={ShopHome} />
</div>
</BrowserRouter>
);
}
}
export default App;
Here is my ButtonAppBar:
import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } from '#material-ui/core/styles';
import AppBar from '#material-ui/core/AppBar';
import Toolbar from '#material-ui/core/Toolbar';
import Typography from '#material-ui/core/Typography';
import Button from '#material-ui/core/Button';
import IconButton from '#material-ui/core/IconButton';
import MenuIcon from '#material-ui/icons/Menu';
import SvgIcon from '#material-ui/core/SvgIcon';
import ShoppingCart from '#material-ui/icons/ShoppingCart';
const styles = {
root: {
flexGrow: 1,
},
grow: {
flexGrow: 1,
},
menuButton: {
marginLeft: -12,
marginRight: 20,
},
appBar: {
marginBottom: 50,
}
};
function ButtonAppBar(props) {
const { classes } = props;
return (
<div className={classes.root}>
<AppBar style={styles.appBar} position="static">
<Toolbar>
<IconButton className={classes.menuButton} color="inherit" aria-label="Menu">
<MenuIcon />
</IconButton>
<Typography variant="h6" color="inherit" className={classes.grow}>
Velo-Velo
</Typography>
<Button color="inherit">Checkout</Button>
<SvgIcon>
<ShoppingCart />
</SvgIcon>
</Toolbar>
</AppBar>
</div>
);
}
ButtonAppBar.propTypes = {
classes: PropTypes.object.isRequired,
};
export default withStyles(styles)(ButtonAppBar);
Here is the modal:
import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } from '#material-ui/core/styles';
import Typography from '#material-ui/core/Typography';
import Modal from '#material-ui/core/Modal';
import Button from '#material-ui/core/Button';
function rand() {
return Math.round(Math.random() * 20) - 10;
}
function getModalStyle() {
const top = 50 + rand();
const left = 50 + rand();
return {
top: `${top}%`,
left: `${left}%`,
transform: `translate(-${top}%, -${left}%)`,
};
}
const styles = theme => ({
paper: {
position: 'absolute',
width: theme.spacing.unit * 50,
backgroundColor: theme.palette.background.paper,
boxShadow: theme.shadows[5],
padding: theme.spacing.unit * 4,
},
});
class SimpleModal extends React.Component {
state = {
open: false,
};
handleOpen = () => {
console.log('clicked')
this.setState({ open: true });
};
handleClose = () => {
this.setState({ open: false });
};
render() {
const { classes } = this.props;
return (
<div>
{/* <Typography gutterBottom>Click to get the full Modal experience!</Typography>
<Button onClick={this.handleOpen}>Open Modal</Button> */}
<Modal
aria-labelledby="simple-modal-title"
aria-describedby="simple-modal-description"
open={this.state.open}
onClose={this.handleClose}
>
<div style={getModalStyle()} className={classes.paper}>
<Typography variant="h6" id="modal-title">
Text in a modal
</Typography>
<Typography variant="subtitle1" id="simple-modal-description">
Duis mollis, est non commodo luctus, nisi erat porttitor ligula.
</Typography>
<SimpleModalWrapped />
</div>
</Modal>
</div>
);
}
}
SimpleModal.propTypes = {
classes: PropTypes.object.isRequired,
};
// We need an intermediary variable for handling the recursive nesting.
const SimpleModalWrapped = withStyles(styles)(SimpleModal);
export default SimpleModalWrapped;
Your best bet is to use something like Redux. As a lazier strategy have a Higher Order Component house both components. The higher order component can have the function which needs to run when you click on the icon and it changes something in the state of the higher order Component.
Say you have:
import React, { Component } from 'react'
import ComponentWithIcon from './icon-holder'
import ModalComponent from './modal'
class OuterContainer extends Component {
state = { modalOpen: false }
setModal = openOrClose => this.setState({modalOpen: openOrClose})
render(){
const {setModal, state: { modalOpen } } = this
return (
<>
<ComponentWithIcon
handleModalClick={setModal}
/>
<ModalComponent
isOpen={modalOpen}
handleModalClick={setModal}
/>
</>
)
}
}
As a result rather than the Modal component determining whether it is open (having it in its own state) which means that only it will know about whether it is presently open that will be determined by the OuterContainer... The OuterContainer is also the one which will handleTheClickEvent which clicking on the icon causes, so instead of running its own function, the icon will run the OuterComponent's function to setState...
This functionality (the clickHandler) and the state is passed to each of those child components through their props. Since the modal needs to be able to close that too can be passed in from the OuterComponent and it can be kept with the same state.modalOpen and possibly the same passed in action (clickHandler) which is toggle (or if you need for some reason then you can have an openModal/closeModal defined by the OuterComponent and pass both of those callbacks to be run by the modal.
Using redux (with react-redux) you have a single <Provider> component which is the higher order components to all of its children. The provider keeps in state a general store which is generated through redux's createStore() this store then gets actions which manipulate the central store and because it is at the top level it is able to inject its current state (or specific parts of it) to any component that is held within the Provider (which is every single component). Each of those components are able to send messages to that provider using dispatch() they then dispatch actions to the store and that results in the store being replaced with a new store that has things updated inside of it (such as whether the modal is open).
import React from 'react'
const MyModal = ({isOpen, handleModal }) => (
<div className={`modal ${isOpen ? 'is-showing' : 'is-hidden'}`}>
<div
className='toolbar'
>
<CloseButton onClick={() => handleModal(false)} />
</div>
<div>
{/* Modal content */}
</div>
</>
)

reactstrap tooltip dynamic id

I am developing a react application and using reactstrap.
I am using Tooltip Component of reactstrap which requires a target attribute, a value of target element's id. This id is being geneated dynamically and seems reactstrap tooltip doesn't like it.
Component looks like:
MovieCard.jsx
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { Col, Card, CardImg, CardBody, CardTitle, CardSubtitle, CardText, Button, Tooltip } from 'reactstrap';
import { LimitedTextTitle } from '../custom-styled/CustomStyledComponents';
class MovieCard extends Component {
constructor (props) {
super(props);
this.state = {
open: false
};
this.toggle = this.toggle.bind(this);
}
toggle () {
this.setState({
open: !this.state.open
})
}
render () {
const { imdbID, Title, Year, Rated, Plot, Country, Poster } = this.props.movie;
return (
<Col md="4">
<Card>
<CardImg
top
width="100%"
src={Poster}
alt="blah"
/>
</Card>
<CardBody>
<CardTitle>
<LimitedTextTitle id={imdbID}>
{`${Title} - (${Year})`}
</LimitedTextTitle>
<Tooltip placement='top' target={imdbID} isOpen={this.state.open} toggle={this.toggle}>
{Title}
</Tooltip>
</CardTitle>
<CardSubtitle>{`Rated: ${Rated} Country: ${Country}`}</CardSubtitle>
<CardText>{Plot}</CardText>
<Button>Read More</Button>
</CardBody>
</Col>
);
}
}
MovieCard.propTypes = {
movie: PropTypes.object.isRequired // eslint-disable-line
};
export default MovieCard;
Any suggestions?
react vesion 16.2.0
reactstrap 5.0.0-alpha.4
Was dealing with a similar problem.
Adding the code as an answer because i cannot add a comment above...
Hope it will help you or anyone else who will come across this question.
Description:
Use reactstrap tooltip for elements that are getting generated dynamically.
import React from 'react';
import ReactDOM from 'react-dom';
import 'bootstrap/dist/css/bootstrap.min.css';
import { Button, Tooltip } from 'reactstrap';
class App extends React.Component {
state = {};
toggle = targetName => {
if (!this.state[targetName]) {
this.setState({
...this.state,
[targetName]: {
tooltipOpen: true
}
});
} else {
this.setState({
...this.state,
[targetName]: {
tooltipOpen: !this.state[targetName].tooltipOpen
}
});
}
};
isToolTipOpen = targetName => {
return this.state[targetName] ? this.state[targetName].tooltipOpen : false;
};
render() {
return (
<div>
{[1, 2, 3, 4, 5, 6].map((x, i) => (
<div key={`div-${i}`}>
<Button color="link" id={`btn-${i}`}>
{x}
</Button>
<Tooltip
placement="right"
isOpen={this.isToolTipOpen(`btn-${i}`)}
target={`btn-${i}`}
toggle={() => this.toggle(`btn-${i}`)}>
Hello world!
</Tooltip>
</div>
))}
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('root'));
react: 16.9.0
reactstrap: 8.0.1
https://codesandbox.io/embed/angry-taussig-fup7i?fontsize=14
EUREKA I GOT IT!!! Building on Meir Keller's answer, there's no need to check if that state for the tooltip already exist. If it doesn't exist, it's false by default...
So long as state is defined, even if it's an empty state, this works.
This is using reactstrap's Popover, but it's the same concept.
import React, { Component, Fragment } from 'react';
import './App.css';
import 'bootstrap/dist/css/bootstrap.min.css'
import { Container, Row, Col, Input, Button, Popover } from 'reactstrap';
class App extends Component {
state = {};
toggle = (target) => {
// console.log(typeof target) // make sure this is a string
this.setState({
...state,
[target]: !this.state[target]
});
};
render() {
return (
<Container>
{["Hello", "Greetings"].map((name) => (
<Row>
<Fragment>
<Button id={name} type="button">{name}</Button>
<Popover placement="right"
isOpen={this.state[`${name}`]}
target={name}
toggle={() => this.toggle(`${name}`)}>
<PopoverBody>
You've got mail. Did you know?
</PopoverBody>
</Popover>
</Fragment>
</Row>
))}
</Container>
);
}
}
export default App;
Create a new component in modular or component directory and paste this code
import React, { useState } from "react";
import { Tooltip } from "reactstrap";
const TooltipItem = props => {
const { position='top', id } = props;
const [tooltipOpen, setTooltipOpen] = useState(false);
const toggle = () => setTooltipOpen(!tooltipOpen);
return (
<span>
<span id={"tooltip-" + id}>
{props.children}
</span>
<Tooltip
placement={position}
isOpen={tooltipOpen}
target={"tooltip-" + id}
toggle={toggle}
>
{props.title}
</Tooltip>
</span>
);
};
export default TooltipItem;
Now import and use this tooltip component
import TooltipItem from "../Tooltip";
<TooltipItem id={'edit' + data.id} title={'Edit Store'}>
<i className="fas fa-edit pointer" onClick={() => this.onEditClick(data)}/>
</TooltipItem>
I will Like to add an answer for it as already many people have mentioned many ways to deal with the problem.
But reactStrap works perfectly fine, mistakes most of the beginners are doing that while creating id they are using special characters like:
- _ / # and it can even be a space
Just keep the id a very simple combination of chars and numbers reactstrap will work totally fine
New component UncontrolledTooltip will solve the problem. Just use
<UncontrolledTooltip
placement="right"
target={`btn-${i}`}
>
{props.title}
</UncontrolledTooltip>
I tried a lot of solutions and was still having trouble with Reactstrap Tooltip crashing when the target element is not in the Dom.
I combined a couple other solutions that people posted and this is the only way it worked for me. Conditional rendering FTW.
const ElementWithTooltip = ({
dynamicIdentifier, // string, number, w/e
}): ReactElement => {
// Target element state.
const [isTargetReady, setIsTargetReady] = useState(false);
// Target element ref.
const tooltipRef = useRef(null);
// Hook to recognize that the target is ready.
useEffect(() => {
const targetElement = tooltipRef.current;
if (targetElement) {
setIsTargetReady(true);
}
}, [tooltipRef.current]);
// TSX.
return (
<>
<span ref={tooltipRef}>This is the target element</span>
{isTargetReady && <UncontrolledTooltip autohide={false} target={tooltipRef}>
Tooltippy text stuff
</UncontrolledTooltip>}
</>
);
The imdbID most probably is starting with digit i.e. 123abcdefghijklmno1234567890
Remember that tooltips can't work in that case when ID starts with a number i.e. the Tooltip's target cannot start with an integer.
all you need to do here is, change this:
<CardTitle>
<LimitedTextTitle id={imdbID}>
{`${Title} - (${Year})`}
</LimitedTextTitle>
<Tooltip placement='top' target={imdbID} isOpen={this.state.open} toggle={this.toggle}>
{Title}
</Tooltip>
</CardTitle>
to this:
<CardTitle>
<LimitedTextTitle id={`movie-${imdbID}`}>
{`${Title} - (${Year})`}
</LimitedTextTitle>
<Tooltip placement='top' target={`movie-${imdbID}`} isOpen={this.state.open} toggle={this.toggle}>
{Title}
</Tooltip>
</CardTitle>
You can avoid using state by simply switching to UncontrolledTooltip which handles all the toggle itself without asking you to handle that explicitly, like:
<CardTitle>
<LimitedTextTitle id={`movie-${imdbID}`}>
{`${Title} - (${Year})`}
</LimitedTextTitle>
<UncontrolledTooltip placement='top' target={`movie-${imdbID}`}>
{Title}
</UncontrolledTooltip>
</CardTitle>
Rendering dynamic content in tooltip in react js is very simple.
Use ReactTooltip.
For full understanding check below example.
Here I am adding requestId in tooltip as dynamically.
{
completedTransactions.map((item, id) => (
<tr key={id + 1}>
<td>{id + 1}</td>
<td>
<span data-tip={item.requestId} data-for="registerTip">
{item.TransactionId}
</span>
<ReactTooltip id="registerTip" place="top" />
</td>
<td>{item.groupName}</td>
<td>{item.purposeName}</td>
<td>{dateFormat(item.update, "dd-mm-yyyy hh:mm tt")}</td>
</tr>
));
}

Resources