Why is props undefined when using react-redux? - javascript

I am new to React and have been trying to look at this code for a while and can't figure out what could be wrong. I am getting an error saying that props is undefined when I try to console.log this.props to the screen.
Here is the code:
import React, { useState } from 'react';
import Grid from '#material-ui/core/Grid';
import InputField from 'shared/components/form/Inputfield';
import DatePicker from 'shared/components/pickers/DatePicker';
import InfoButton from 'shared/components/buttons/InfoButton';
import CustomButton from 'shared/components/buttons/CustomButton';
import TextArea from 'shared/components/form/TextArea';
import { connect } from 'react-redux';
export function ProjectDetails() {
const [values, setValues] = React.useState({
full_project_name: ' ',
short_name: ' ',
associated_projects: ' ',
short_description: ' ',
summary: ' ',
url_to_webpage: ' ',
start_date: ' ',
end_date: ' ',
});
const handleNameChange = full_project_name => event => {
console.log('Props of this object', this.props);
setValues({ ...values, [full_project_name]: event.target.value });
};
const handleShortNameChange = short_name => event => {
setValues({ ...values, [short_name]: event.target.short_name });
};
console.log('Project values', { values });
return (
<>
<h1>Project Details</h1>
<Grid container spacing={1}>
<Grid item xs={12}>
<h3>Full project name *</h3>
</Grid>
<Grid item xs={12}>
<InputField handler={handleNameChange('full_project_name')} />
</Grid>
<Grid item xs={12}>
<h3>Short name (Acronym)</h3>
</Grid>
<Grid item xs={12}>
<InputField handler={handleShortNameChange('short_name')} />
</Grid>
<Grid item xs={12}>
<h3>
Associated Projects <InfoButton />
</h3>
</Grid>
<Grid item xs={11}>
<InputField placeHolderText="Search Project" />
</Grid>
<Grid item xs={1}>
<CustomButton buttonType="Add" text="Add" />
</Grid>
<Grid item xs={12}>
<h3>
Short Description * <InfoButton />
</h3>
</Grid>
<Grid item xs={12}>
<TextArea maxChars={350} />
</Grid>
<Grid item xs={12}>
<h3>
Summary * <InfoButton />
</h3>
</Grid>
<Grid item xs={12}>
<TextArea maxChars={4000} />
</Grid>
<Grid item xs={12}>
<h3>URL to Web Page</h3>
</Grid>
<Grid item xs={12}>
<InputField />
</Grid>
<Grid item xs={6}>
<h3>Start date *</h3>
</Grid>
<Grid item xs={6}>
<h3>End date *</h3>
</Grid>
<Grid item xs={12}>
<h3>
<DatePicker />
</h3>
</Grid>
</Grid>
</>
);
}
function mapStateToProps(state) {
console.log('The state when map happens is: ', state);
return {
full_project_name: state.projectReducer.full_project_name,
short_name: state.projectReducer.short_name,
associated_projects: state.projectReducer.associated_projects,
short_description: state.projectReducer.short_description,
summary: state.projectReducer.summary,
url_to_webpage: state.projectReducer.url_to_webpage,
start_date: state.projectReducer.start_date,
end_date: state.projectReducer.end_date,
};
}
export default connect(mapStateToProps)(ProjectDetails);
When the handleNameChange()-method is called props are undefined. I think I might be using connect wrong. Can anyone help me out?

In a functional component, you cannot access this
Try this instead:
export function ProjectDetails(props) {
const handleNameChange = full_project_name => event => {
console.log('Props of this object', props);
}
}
We get access to props from arguments of the function.
Have a read in react docs: https://reactjs.org/docs/components-and-props.html

Related

React : How do I trigger function that change style inside the child component when hovering parent

Recently I made a component of the Item called ItemsPageItem inside of it I have a couple of other components and the one is called OnHoverAboutBlock should change some styles of inside located Grid. I made flag for the OnHoverAboutBlock which I am passing in props, looks like this:
export default function ItemsPageItemContent({serialNum, title, price, shortDescription, type}) {
const localStyles = useStyles();
const [isHover, setIsHover] = useState(false);
function onEnter(e){
e.target.style.position = "absolute";
e.target.style.overflow = "visible";
e.target.style.height = 350;
}
function onLeave(e){
e.target.style.position = "relative";
e.target.style.overflow = "hidden";
e.target.style.height = 135;
}
return (
<>
<Grid container onMouseEnter={`${() => setIsHover(true)}`} onMouseLeave={`${() => setIsHover(false)}`} className={localStyles.itemBoxContainer}>
<Grid item className={localStyles.itemBox} xs={12}>
<Grid item xs={12} className={localStyles.widgetBlock}>
<Grid item xs={2}>
<SerialNumber serialNumber={serialNum}/>
</Grid>
<Grid item className={localStyles.typeBox} xs={8}>
<TypeOfLot type={type}/>
</Grid>
<Grid item xs={2}>
</Grid>
</Grid>
</Grid>
<OnHoverAboutBlock **isHover={isHover}** title={title} price={price}
desc={shortDescription} type={type}/>
</Grid>
</>
);
The question is how do I trigger the functions onEnter onLeave inside the child.
I tried to write these functions inside the OnHoverAboutBlock but I still don't understand how do I trigger these functions. The code of OnHoverAboutBlock look like this :
export const OnHoverAboutBlock = ({title, price, desc, type, **isHover**}) => {
const localStyles = useStyles();
let buttonText = "Place Bid";
switch (type) {
case "Product":
buttonText = "Buy Now";
break;
case "Donation":
buttonText = "Make Donation";
break;
default:
break;
}
return (
<>
<Grid item className={`${localStyles.hoverAboutBlock}`} xs={12}>
<Grid item className={localStyles.mainDesc} xs={12}>
<Typography className={localStyles.secondaryTextColor} variant="h5" component="h2">
{title}
</Typography>
<Typography variant="subtitle2">
{price}
</Typography>
</Grid>
<Grid item xs={12}>
<Typography variant="body1" className={localStyles.bodyTextColor}>
{desc}
</Typography>
</Grid>
<Grid item className={localStyles.bottomWidgetsBlock} xs={12}>
<Grid item xs={8}>
<Button className={localStyles.button}>
{buttonText}
</Button>
</Grid>
<Grid item className={localStyles.likePlusBlock} xs={4}>
<Fab className={localStyles.bottomWidgetButtons}>
<AddIcon/>
</Fab>
<Fab>
<LikeIcon/>
</Fab>
</Grid>
</Grid>
</Grid>
</>
)
}
So, as well as I understand, you are trying to change the styles of the child component based on hovering over the parent. I see you already have created an isHover and you are setting it to true on mouse enter and false on mouse leave. Since you are already passing isHover as a prop to the child component, what you can do is use a condition inside your child component as follows
let customStyleClasses = "";
if(isHover){
customStyleClasses = "styles-you-wanted-to-define-for-the-child-component"
}
Now you can add this customStyleClasses to your Grid component as follows:
export const OnHoverAboutBlock = ({title, price, desc, type, **isHover**}) => {
.
.
.
return (
<>
<Grid item className={`${localStyles.hoverAboutBlock} ${customStyleClasses }`} xs={12}>
.
.
.
.
);
}

React js material ui Grid responsive

As you can see from the image on the left I have a map with the controls, on the right I have a series of fields (last update, a table and an input field).
What I would like to do is that when it reaches a certain size (device example) the right side goes down under the map, the map then takes all the available space.
As you can see from the image when you resize a part of the table you do not see, you have to scroll.
Can you give me a hand?
In the original project I also use:
"tailwindcss": "1.2.0",
"tailwindcss-dir": "4.0.0"
Link: codesandbox
Code:
import React from "react";
import { makeStyles } from "#material-ui/core/styles";
import {
Grid,
TextField,
Paper,
Typography,
Tooltip,
Chip
} from "#material-ui/core";
import { red, teal } from "#material-ui/core/colors";
import Map from "./Map";
import ToggleButtonMap from "./ToggleButtonMap";
import DataTable from "react-data-table-component";
import "./styles.css";
const useStyles = makeStyles((theme) => ({
root: {},
paper: {
display: "flex",
border: `1px solid ${theme.palette.divider}`,
flexWrap: "wrap",
padding: 10
},
control: {}
}));
export default function App() {
const [state, setState] = React.useState({
historyParking: [
{
idPs: "7ff2-4e5d-b164-661b511e609e-1",
free: false,
latitude: 33,
longitude: 10,
timeCurrent: "23/10/2020 15:13:23"
},
{
idPs: "7ff2-4e5d-b164-661b511e609e-1",
free: true,
latitude: 33,
longitude: 10,
timeCurrent: "23/10/2020 15:13:23"
}
]
});
const { historyParking } = state;
const classes = useStyles();
const columns = [
{
name: "Name",
selector: "idPs",
cell: ({ idPs }) => (
<Tooltip title={`${idPs}`} placement="right-start" arrow>
<span>{shortCode(camPlace(idPs).idPs)}</span>
</Tooltip>
)
},
{
name: "Place",
selector: "idPs",
cell: ({ idPs }) => camPlace(idPs).place
},
{
name: "Status",
selector: "free",
cell: ({ free }) => (
<div>
<Chip
variant="outlined"
style={{
color: free ? teal["600"] : red["600"],
borderColor: free ? teal["600"] : red["600"]
}}
label={`${fixName(free?.toString())}`}
size="small"
/>
</div>
)
},
{
name: "Last update",
selector: "timeCurrent",
cell: ({ timeCurrent }) => (
<Tooltip title={`${timeCurrent}`} placement="right-start" arrow>
<span>{timeCurrent}</span>
</Tooltip>
)
}
];
const shortCode = (code, left = 10, right = 10) => {
return `${code.substring(0, left)}...${code.substring(
code.length - right,
code.length
)}`;
};
const fixName = (name) => {
return name
?.replace("_", " ")
.toLowerCase()
.split(" ")
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
.join(" ");
};
const camPlace = (a) => {
const idPs = a.split("-");
const place = idPs.pop();
return { idPs: idPs.join("-"), place };
};
return (
<>
<Grid container spacing={2}>
<Grid item xs={8}>
<Paper elevation={1} className={classes.paper}>
<Grid container spacing={2}>
<Grid item>
<ToggleButtonMap />
</Grid>
<Grid item xs={12} sm={12} className="h-512">
<Map />
</Grid>
</Grid>
</Paper>
</Grid>
<Grid item xs={4}>
<Grid container direction="column" spacing={1}>
<Grid item>
<TextField
id="city_zone"
variant="outlined"
size="small"
></TextField>
</Grid>
<Grid item>
<Typography component="div">
Last update: 23/10/2020 16:31:35
</Typography>
</Grid>
<Grid item>
<div
style={{
border: "1px solid #dadce0",
backgroundColor: "#fff",
marginTop: 5
}}
>
<DataTable
title={"History"}
columns={columns}
data={historyParking}
highlightOnHover
defaultSortField="timeCurrent"
defaultSortAsc={false}
pagination
paginationPerPage={6}
/>
</div>
</Grid>
</Grid>
</Grid>
</Grid>
</>
);
}
This might be what you are looking for
<Grid item xs={8} sm={12}>
<Paper elevation={1} className={classes.paper}>
<Grid container spacing={2}>
<Grid item>
<ToggleButtonMap />
</Grid>
<Grid item xs={12} className="h-512">
<Map />
</Grid>
</Grid>
</Paper>
</Grid>

What is the problem of glitch when scrolling using react-window?

I want to do row virtualization when scrolling (so that data is shown when scrolling)
But when scrolling, now the terrible glitches appear
Tell me what is the problem?
project - male-wind.surge.sh
A component with a table (react-window is used there):
import React, { Component } from "react";
import { connect } from "react-redux";
import actions from "../../actions";
import PropTypes from "prop-types";
import sort from "./sort";
import { FixedSizeList } from 'react-window';
function TitleColumn(data) {
return (
<Grid item xs={1}>
<Box className="title_elem">
<h3
className="table_title-text"
onClick={sort.bind(null, `${data.title.toLowerCase()}`, data.props)}
>
{data.title}
</h3>
{data.props.fourthData.data === `${data.title.toLowerCase()}` ? (
<p>{data.props.fifthData.data}</p>
) : null}
</Box>
</Grid>
);
}
class Table extends Component {
render() {
const data = this.props.info;
const Row = ({ index, style}) => {
return (
<Grid container className="table_row">
<Grid item xs={1}>
<Box className="table_elem name_elem">{data[index].name}</Box>
</Grid>
<Grid item xs={1}>
<Box className="table_elem job_elem">{data[index].job}</Box>
</Grid>
<Grid item xs={1}>
<Box className="table_elem city_elem">{data[index].city}</Box>
</Grid>
<Grid item xs={1}>
<Box className="table_elem country_elem">{data[index].country}</Box>
</Grid>
<Grid item xs={1}>
<Box className="table_elem latitude_elem">{data[index].latitude}</Box>
</Grid>
<Grid item xs={1}>
<Box className="table_elem longitude_elem">{data[index].longitude}</Box>
</Grid>
<Grid item xs={1}>
<Box className="table_elem date_elem">
{`${data[index].date.toLocaleString("en", {
year: "numeric",
month: "long",
day: "numeric"
})}`}
</Box>
</Grid>
</Grid>
)
};
return (
<Grid
container
className="developer_block-time_feature time_feature_block"
>
<Grid container className="table_title">
<TitleColumn props={this.props} title="Name" />
<TitleColumn props={this.props} title="Job" />
<TitleColumn props={this.props} title="City" />
<TitleColumn props={this.props} title="Country" />
<TitleColumn props={this.props} title="Latitude" />
<TitleColumn props={this.props} title="Longitude" />
<TitleColumn props={this.props} title="Date" />
</Grid>
<FixedSizeList <---------------use react-window
height={500}
itemSize={60}
itemCount={data.length}
className="list-container"
>
{Row}
</FixedSizeList>
</Grid>
);
}
}
Table.propTypes = {
fourthData: PropTypes.object.isRequired,
fifthData: PropTypes.object.isRequired
};
const mapStateToProps = store => {
return {
firstData: store.firstData,
secondData: store.secondData,
thirdData: store.thirdData,
fourthData: store.fourthData,
fifthData: store.fifthData
};
};
const mapDispatchToProps = dispatch => {
return {
setData: data => dispatch(actions.setData(data)),
changeSearchData: searchData =>
dispatch(actions.changeSearchData(searchData)),
changeSort: sort => dispatch(actions.changeSort(sort)),
setSortTitle: sortField => dispatch(actions.setSortTitle(sortField)),
changeArrow: arrow => dispatch(actions.changeArrow(arrow))
};
};
export default connect(mapStateToProps, mapDispatchToProps)(Table);
I try to use this solution, but it does not help - https://github.com/bvaughn/react-virtualized/issues/1327
you have to apply the style passed by list for list element rendering which sets height, width and top attributes. you can do as below
const Row = ({ index, style}) => {
return (
<Grid container className="table_row" style={style}>
<Grid item xs={1}>
<Box className="table_elem name_elem">{data[index].name}</Box>
</Grid>....…..

How can I store the information and render this hook in ReactJS?

I use a button from another component to access this Favorites component, but when I press the button, it doesn't load anything and the page goes blank. Now if I press the button twice, it shows me the information.
const Favorites = (props) => {
const [products, setProducts] = useState([]);
useEffect(() =>{
let productsArray = []
firebase.database().ref().child('favorites').orderByKey()
.once('value', snap => {
snap.forEach(child => {
if(child.val().user_id === firebase.auth().currentUser.uid){
firebase.database().ref('products/' + child.val().product_id)
.once('value')
.then(snapshot =>{
const favorite = {
id: snapshot.key,
name: snapshot.val().name,
category: snapshot.val().category,
description: snapshot.val().description,
image: snapshot.val().image,
price: snapshot.val().price,
stock: snapshot.val().stock,
};
productsArray.push(favorite);
});
}
});
setProducts(productsArray);
});
},[]);
return (
<Fragment>
<ul>
{ products && products.map((item, index) => {
return(
<Grid container justify="center" alignItems="center" key={index}>
<div className={classes.root}>
<Paper className={classes.paper}>
<Grid container spacing={2}>
<Grid item>
<ButtonBase className={classes.image}>
<img className={classes.img} alt="complex" src={item.image} />
</ButtonBase>
</Grid>
<Grid item xs={12} sm container>
<Grid item xs container direction="column" spacing={2}>
<Grid item xs>
<Typography gutterBottom variant="subtitle1">
{item.name}
</Typography>
<Typography variant="body2" gutterBottom>
{"Categoria: " + item.category}
</Typography>
<Typography variant="body2" color="textSecondary">
{item.description}
</Typography>
</Grid>
<Grid item>
<Button
onClick={(event) => removeFavorite(event, index)}>
<HighlightOff/> Eliminar de Favoritos
</Button>
</Grid>
</Grid>
<Grid item>
<Typography variant="subtitle1">{"Bs " + item.price + "/ Kg"}</Typography>
</Grid>
</Grid>
</Grid>
</Paper>
</div>
</Grid>
);
})
}
</ul>
</Fragment>
);
}
export default Favorites;
I think I am doing something wrong with the useEffect() when I perform the query and store it with the setProducts() fix. I don't know what's happening, why does it go blank and then rerun the Favorites component if it shows? I appreciate your help.
In the App component I have the Shopping Cart Sharp button, which redirects to "/ shoppingcart", which is the component where I have the problem.
const MyLink = React.forwardRef((props, ref) => <RouterLink innerRef={ref}
{...props} />);
function App() {
const [user, setUser] = useState(null);
const onLogout = () => {
setUser(null);
};
return (
<Router>
<CssBaseLine/>
<Header user={user}>
{user && <Button to="/shoppingcart" component={MyLink}
color="inherit"><ShoppingCartSharp /></Button>}
</Header>
<Routes/>
</Router>
);
}
export default App;

Trouble with Grid Layout in React Material UI

I'm trying to achieve a specific layout using the Material UI Grid Component, but I just cannot for the life of me get it right.
I have a Dialog where I want the Layout to end up like this:
Where the blue box contains some information about a project, the green box will contain some sort of media and the yellow box will contain a descriptive text.
But currently, with this code, it ends up like this:
<Grid xl={12}>
<Grid spacing={0} xs={2}>
<Grid container direction="column">
<Grid item xs={1}>
{ this.getGridItems("Platforms", data["platforms"].split(','), true) }
</Grid>
<Grid item xs={1}>
{ this.getGridItems("Engines", data["engines"].split(','), true) }
</Grid>
<Grid item xs={1}>
{ this.getGridItems("Frameworks", data["frameworks"].split(','), true) }
</Grid>
<Grid item xs={1}>
{ this.getGridItems("Languages", data["languages"].split(',')) }
</Grid>
<Grid item xs={1}>
{ this.getGridItems("Roles", data["roles"].split(',')) }
</Grid>
</Grid>
</Grid>
<Grid spacing={0} xl={10}>
<Grid container>
<Grid item xl={9}>
<h1>Image Goes Here</h1>
</Grid>
<Grid item xl={3}>
<h1>Description</h1>
{ data["description"] }
</Grid>
</Grid>
</Grid>
</Grid>
I cannot quite figure out where I went wrong as I can't wrap my head around how the Grid layout works. Please help?
If it's necessary, here is the code for getGridItems():
getGridItems = (header, data, chips) => {
let list = [];
let fontSize = 11;
list.push(
<h5>{ header }</h5>
);
if(data.length > 0 && data[0] !== '') {
if(chips !== undefined && true) {
data.forEach(value => {
let chipData = ChipConstants[value];
list.push(
<Grid item xs>
<Chip
style={{ fontSize: fontSize}}
avatar={
<Avatar
style={{ width: 24, height: 24 }}
alt={chipData["avatar"]["alt"]}
src={require("../img/avatars/"+chipData["avatar"]["img"])}
/>}
label={chipData["avatar"]["alt"]}
className={styles.chip}
/>
</Grid>
);
});
} else {
data.forEach(value => {
list.push(
<Grid item xs style={{ fontSize: fontSize}}>
{ value }
</Grid>
);
});
}
} else {
list.push(
<Grid item xs style={{ fontSize: fontSize}}>
None
</Grid>
);
}
return list;
};
I'm not really seeing how your current code relates to what you want, so instead of trying to correct your current code, I'll just provide a starting point that provides the basic structure of what you want.
If you have specific questions about how the Grid in my code works, I'll elaborate as needed.
index.js
import React from "react";
import ReactDOM from "react-dom";
import CssBaseline from "#material-ui/core/CssBaseline";
import Button from "#material-ui/core/Button";
import MyDialog from "./MyDialog";
class App extends React.Component {
state = {
open: false
};
handleClickOpen = () => {
this.setState({ open: true });
};
handleClose = () => {
this.setState({ open: false });
};
render() {
return (
<>
<CssBaseline />
<Button variant="contained" onClick={this.handleClickOpen}>
Open Dialog
</Button>
<MyDialog open={this.state.open} handleClose={this.handleClose} />
</>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
MyDialog.js
import React from "react";
import Grid from "#material-ui/core/Grid";
import Dialog from "#material-ui/core/Dialog";
import IconButton from "#material-ui/core/IconButton";
import CloseIcon from "#material-ui/icons/Close";
import { withStyles } from "#material-ui/core/styles";
const styles = {
root: {
height: "100%"
},
project: {
backgroundColor: "lightblue",
height: "100%"
},
right: {
height: "100%"
},
media: {
backgroundColor: "lightgreen",
height: "70%"
},
desc: {
backgroundColor: "yellow",
height: "30%"
}
};
const MyDialog = props => {
return (
<Dialog fullScreen open={props.open} onClose={props.handleClose}>
<Grid container className={props.classes.root}>
<Grid item xs={3} className={props.classes.project}>
<IconButton
color="inherit"
onClick={props.handleClose}
aria-label="Close"
>
<CloseIcon />
</IconButton>
Project
</Grid>
<Grid item xs={9}>
<Grid container direction="column" className={props.classes.right}>
<Grid item className={props.classes.media}>
Media
</Grid>
<Grid item className={props.classes.desc}>
Description
</Grid>
</Grid>
</Grid>
</Grid>
</Dialog>
);
};
export default withStyles(styles)(MyDialog);
Here it is in a CodeSandbox you can experiment with:

Categories