React.js with Redux: Get info from state - reactjs

I'm coding the app and I can't solve a problem. I have stored user info in the state (when I open Redux DevTools I can see the state -> user: {username: name, role: ...}).
Now in some components, I want to check if logged in user is admin or a user. I have it in that state but how can I load it in some class? When I export a function, I can use const userRole = useSelector(state => state.security.user.role_id); but in a class it makes a problem. Can you help me?
this is my code for User class and I want to show up DELETE button, only if user is an admin:
import React, {Component} from "react";
import PropTypes from "prop-types";
import {connect, useSelector} from "react-redux";
import { Link } from "react-router-dom";
import { deleteUser } from "../../store/actions/userActions";
class User extends Component{
constructor() {
super();}
onDeleteClick(id) {
this.props.deleteUser(id);
}
render() {
const { user } = this.props;
return (
<div className='row entry'>
<div className='col-sm-2'>
<span >{user.username}</span>
</div>
<div className='col-sm-2'>
<span >{user.name}</span>
</div>
<div className='col-sm-2'>
<span>{user.lastname}</span>
</div>
<div className='col-sm-2'>
<span>{user.tag}</span>
</div>
<div className='col-sm-1'>
<span>{user.pay}</span>
</div>
<div className='col-sm-1'>
<span>
{user.role_id}
</span>
</div>
<div className='col-sm-2'>
<Link to={`userlist/edituser:${user.id}`}>
<button><i className="fas fa-user-edit"></i></button>
</Link> | <button onClick={this.onDeleteClick.bind(this, user.id)}><i className="far fa-trash-alt"></i></button>
</div>
</div>
)
}
}
User.propTypes = {
deleteUser: PropTypes.func.isRequired
};
export default connect(
null, { deleteUser }
)(User);

With class components, you can make use of connect HOC with mapStateToProps to access state from redux
class User extends Component{
render() {
const { user, userRole } = this.props;
...
}
}
const mapStateToProps = (state) => {
return {
useRole: state.security.user.role_id,
}
}
export default connect(
mapStateToProps, { deleteUser }
)(User);

Related

How to add button cart in shopping cart react redux?

how to add an action when the add button is clicked then the item will display the product?
This code does not display the product when clicked
I've been fiddling with it but it's still an error, who knows, someone here can help me and fix the code and explain it
cartAction.js
import {ADD_TO_CART} from './ActionType';
export const addToCart = (items) =>{
return{
type: ADD_TO_CART,
items //I'm confused about what to do in the action payload here
}
}
cartReducer.js
import ImgT from './images/image-product-1-thumbnail.jpg';
import {ADD_TO_CART} from './ActionType';
const initState = {
items: [
{id:1,title:'title',
brand:cc',
images:ImgT,
desc:'helo world',
price:125.00}
],addItems:[],
total:0
}
const cartReducer= (state = initState,action)=>{
if(action.type === ADD_TO_CART){
return {...state, addItems:state.addItems} //I'm confused about what to do in the action payload here
}
return state
}
export default cartReducer;
cart.js
import React, { Component } from 'react';
import { connect } from 'react-redux';
class Cart extends Component {
render() {
return (
<div>
{this.props.Items.map(item =>{
<div key={item.id}>
{/* <img src={item.images} /> */}
<p>{item.title}</p>
<h4>brand: {item.brand}</h4>
<p>{item.price}</p>
</div>
})
}
</div>
);
}
}
const mapToProps = (state ) =>{
return{
Items:state.addItems}
}
export default connect(mapToProps)(Cart);
Home.js
import React, { Component } from 'react';
import { connect } from 'react-redux';
import Cart from './Cart';
import {addToCart} from './cartAction';
class Home extends Component{
handleClick = () =>{
this.props.addToCart()
}
render(){
let item = this.props.items.map(item =>{
return(
<div className='card' key={item}>
<img style={{width:'10rem'}} src={item.images}/>
<p className='card-title '>{item.title}</p>
<h2 className='card-title fs-4'>{item.brand}</h2>
<button onClick={() => this.handleClick()} className='btn btn-primary'>Add to cart</button>
<h3 className='fs-5'>{item.price}</h3>
</div>
)
})
return(
<div className="container">
<h3>Home</h3>
{item}
<Cart/>
</div>
)
}
}
const mapToProps = (state) => {
return{
items:state.items,
}
}
const mapDispatchToProps = (dispatch) => {
return{
addToCart: () => dispatch(addToCart())}
}
export default connect(mapToProps,mapDispatchToProps)(Home);

React - Redux dispatcher not mapping

I have a several react components in react-redux application. Most of them are working find, but the below "TagItemWidget" does not appear to bind the state or dispatchers to props. I have confirmed that the dispatch function works and fires the reducer. The same function and state can be bound on other components. I have done a trace and observed that the bind function is firing. However, in both "console.log" outputs, props is empty. componentDidMount and render appear to be called only once, when the page loads - never again. What gives?
UPDATE: If I move my <TagItemWidget /> into the spot where <TagItemButton /> is, it populates the dispatchers. Is there a problem with my TagItemButton?
TagItemWidget:
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import { tags_list } from "../../actions/tags";
export class TagItemWidget extends React.Component {
static propTypes = {
cases: PropTypes.array.isRequired,
activeCase: PropTypes.string
};
constructor(props) {
super(props);
}
componentDidMount() {
console.log(this)
}
render() {
console.log(this)
return (
<Fragment>
<div key={Math.random} >
{this.props.activeCase}
</div>
</Fragment>
)
}
}
const mapStateToProps = (state) => ({
cases: state.tags.tags,
activeCase: state.cases.activeCase
});
export default connect(mapStateToProps, { tags_list })(TagItemWidget);
The including component, TagItemButton:
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import { TagItemWidget } from './TagItemWidget';
export class TagItemButton extends Component {
render() {
return (
<Fragment>
<a href="#" className="list-group-item list-group-item-action" id="controls_tagitem"
data-toggle="modal" data-target="#tagItemModal">
Tag Item
</a>
<div className="modal fade" id="tagItemModal" tabIndex="-1"
role="dialog" aria-labelledby="tagItemModalLabel"
aria-hidden="true">
<div className="modal-dialog" role="document">
<div className="modal-content">
<div className="modal-header">
<h5 className="modal-title"
id="tagItemModalLabel">
Tag Item
</h5>
<button type="button" className="close"
data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div className="modal-body">
<TagItemWidget />
</div>
</div>
</div>
</div>
</Fragment>
)
}
}
export default TagItemButton;
actions/tags.js
import { TAGS_LIST } from "./types";
import { createMessage, returnErrors } from "./messages";
export const tags_list = ( case_id ) => dispatch => {
if ( case_id != null ) {
console.log("dispatging TAGS_LIST")
axios
.get("/OMNI_api/api/tag/listbycase/?case_id="+case_id)
.then(response => {
dispatch
({
type: TAGS_LIST,
payload: response.data
})
})
}
}
If you are using redux-thunk. Which I think you are.
dispatch needs to be spread from the thunk like so
export const tags_list = ( case_id ) => ({ dispatch }) => {
You need to bindActionCreators
either before passing them to the connect function
const mapDispatch = (dispatch) => bindActionCreators({ tag_list }, dispatch);
export default connect(mapStateToProps, mapDispatch)(TagItemWidget);
inside the constructor
https://redux.js.org/api/bindactioncreators

How do I reorder/sort Firebase data in React App?

So I'm flying by the seat of my pants here, and I need help reordering a data set. Here's the base of my react component. This is a personal project that I'm doing to then reuse at work for an actual project. The base of this came from a YouTube series about React + Firebase: https://www.youtube.com/playlist?list=PL4cUxeGkcC9iWstfXntcj8f-dFZ4UtlN3
Ideally, I'd like a set of buttons that will sort the data from asc or desc. And maybe dependent on some other things.
import React, { Component } from 'react';
import ShopList from '../shops/ShopList.js';
import { Helmet } from 'react-helmet';
import { connect } from 'react-redux';
import { firestoreConnect } from 'react-redux-firebase';
import { compose } from 'redux';
class Dashboard extends Component {
reOrder = (e) => {
e.preventDefault();
console.log("button works!");
}
render() {
const { shops } = this.props;
return(
<div className="dashboard container">
<Helmet>
<title>Dashboard | Indianapolis Coffee Guide</title>
</Helmet>
<div className="row">
<div className="col-sm-6">
<button className="btn btn-primary" onClick={this.reOrder}>Reorder</button>
</div>
</div>
<div className="row">
<ShopList shops={shops} />
</div>
</div>
)
}
}
const mapStateToProps = (state) => {
return {
shops: state.firestore.ordered.coffeeShops,
auth: state.firebase.auth
}
}
export default compose(
connect(mapStateToProps),
firestoreConnect([
{ collection: 'coffeeShops', orderBy: ['shopName', 'asc']}
])
)(Dashboard)
The data is being ordered right now at the end with the orderBy, but I need to be able to update that...
Thanks for your help!
I am not sure it would work, because I have never used react-redux-firebase, but it seems to me you could create a redux action that sets the ordering direction in redux store. Like this:
import React, { Component } from 'react';
import ShopList from '../shops/ShopList.js';
import { Helmet } from 'react-helmet';
import { connect } from 'react-redux';
import { firestoreConnect } from 'react-redux-firebase';
import { compose } from 'redux';
class Dashboard extends Component {
reOrder = (e) => {
e.preventDefault();
console.log("button works!");
const orderDirection = this.props.orderDirection === 'asc' ? 'desc' : 'asc';
this.props.dispatch(ReOderAction(orderDirection));
}
render() {
const { shops } = this.props;
return(
<div className="dashboard container">
<Helmet>
<title>Dashboard | Indianapolis Coffee Guide</title>
</Helmet>
<div className="row">
<div className="col-sm-6">
<button className="btn btn-primary" onClick={this.reOrder}>Reorder</button>
</div>
</div>
<div className="row">
<ShopList shops={shops} />
</div>
</div>
)
}
}
const mapStateToProps = (state) => {
return {
shops: state.firestore.ordered.coffeeShops,
auth: state.firebase.auth,
orderDirection: state.anything.orderDirection,
}
}
export default compose(
connect(mapStateToProps),
firestoreConnect([
{ collection: 'coffeeShops', orderBy: ['shopName', orderDirection]}
])
)(Dashboard)
Please, let me know if it worked...

TypeError: this.props.decrementCount is not a function

I am trying to make a simple cart counter but getting this error. I am confuse that mapStateToDispatch is working or not. Imported all modules,functions properly but getting only this error when i click the ADD,Remove button
import React,{Component} from 'react';
import './cart.css';
import {product,product1} from './product.js'
import 'bootstrap/dist/css/bootstrap.min.css';
import {incrementCount , decrementCount} from './actions/buttonBehave';
import {connect} from 'react-redux';
import { bindActionCreators } from 'redux'
export class Cart extends Component{
state = {
buttonClicked : false
}
handleButton= () =>{
this.setState({
buttonClicked : true
})
}
render()
{
return(
<div className="cardDiv">
<div className="card" >
<img className="card-img-top" src={product.image} alt="Card image" height="350px" />
<div className="card-body">
<h4 className="card-title">{product.name}</h4>
<p className="card-text">Model : {product.modelName}</p>
<p className="card-text">Price : {product.price}</p>
<a href="#" className="btn btn-primary " onClick={this.handleButton.bind(this)}> {this.state.buttonClicked ? "Add another" : "Add to cart"} </a>
<p className="card-text">Added : {this.props.count}</p>
<button onClick = { () => this.props.incrementCount ()}>Remove</button>
<button onClick = { () => this.props.decrementCount()}>ADD</button>
<p className="card-text">{this.props.count}</p>
</div>
</div>
</div>
);
}
}
const mapStateToProps= (state) =>{
return{
count : state.count
}
}
const mapDispatchToProps = () => {
return {
incrementCount,
decrementCount
}
}
export default connect(mapStateToProps,mapDispatchToProps())(Cart);
You are calling the function instead of passing its reference
export default connect(mapStateToProps,mapDispatchToProps())(Cart);
// ------------------------------------------------------^^--------
change to this
export default connect(mapStateToProps, mapDispatchToProps)(Cart);
An alternative is to just not use mapDispatchToProps at all and use the dispatch your connected component receives
export default connect(mapStateToProps)(Cart);
and then using dispatch
this.props.dispatch(decrementCount())

Context Provider is not working in React.js

I am a beginner in React js and I'm trying to implement Context Provider in React js. But while I'm not getting the perfect output.
I am storing contact info in context.js which will act as Context Provider and in App.js I imported it in App.js then in Contacts.js I Consumed the Consumer and got the value but still, I'm getting the blank page and I'm not sure why I cannot bind the contact component in Context provider
Context.js
import React, {Component} from 'react';
const Context = React.createContext();
export class Provider extends Component {
state = {
contacts: [{
id: 1,
name: "dasd B",
email: "asdas#gmail.com",
phone: "dsadas"
}
};
render() {
debugger
return (
<Context.Provider value={this.state}>
{this.props.childern}
</Context.Provider>
);
}
}
export const Consumer = Context.Consumer;
App.js
import React, { Component } from 'react';
import Header from './components/Header';
import Contacts from './components/Contacts'
import 'bootstrap/dist/css/bootstrap.min.css';
import { Provider } from './Context'
class App extends Component {
render() {
return (
<Provider>
<div className="App">
<div className="container">
<Contacts />
</div>
</div>
</Provider>
);
}
}
export default App;
Contacts.js
import React, { Component } from 'react'
import Contact from './Contact';
import { Consumer } from '../Context';
class Contacts extends Component {
deleteContact = id => {
const { contacts } = this.state;
const newContacts = contacts.filter(contact => contact.id!== id);
this.setState({
contacts: newContacts
});
};
render() {
debugger
return(
<Consumer>
{value => {
const { contacts } = value;
return (
<React.Fragment >
{contacts.map(contact => (
<Contact
key = {contact.id}
contact={contact}
deleteClickHandler = {this.deleteContact.bind(this, contact.id)}>
</Contact>
))}
</React.Fragment>
);
}}
</Consumer>
);
}
}
export default Contacts;
Contact.js
import React, { Component } from 'react'
import PropTypes from 'prop-types'
class Contact extends Component {
state = {
showContactinfo : false
};
onDeleteClick = () => {
this.props.deleteClickHandler();
}
onEditClick() {
}
render() {
const { name, email, phone } =this.props.contact;
const { showContactinfo } = this.state;
return (
<div className="card card-body mb-3">
<h4>{name}
{showContactinfo ? (
<div className="float-right">
<i
onClick= {this.onEditClick}
style={{cursor: 'pointer', fontSize: 'medium'}}
className="fas fa-edit mr-3"></i>
<i
onClick= {this.onDeleteClick}
style={{cursor: 'pointer', fontSize: 'medium'}}
className="fa fa-trash-alt"></i>
</div>):
<i className="fa fa-sort-down float-right"
style={{cursor: 'pointer'}}
onClick={() =>
this.setState({ showContactinfo: !this.state.showContactinfo})}></i>}
</h4>
{showContactinfo ? (
<ul className="list-group">
<li className="list-group-item">Email: {email}</li>
<li className="list-group-item">Phone: {phone}</li>
</ul>) : null}
</div>
)
}
}
Contact.propTypes = {
contact: PropTypes.object.isRequired,
deleteClickHandler: PropTypes.func.isRequired
}
export default Contact;

Resources