React function component not rendering an app component - javascript

I'm a newbie to React. My array of messages is not rendering. I've verified that my array, which is part of the Messages state, is getting made properly, so I'm really confused as to why this is happening. Do I need to make all the components functional components?
ChatApp.js uses Messages.js which is a list that is generated from Message.js
ChatApp.js
import React, {useState} from 'react';
import config from '../config';
import Messages from './Messages';
import ChatInput from './ChatInput';
import Container from 'react-bootstrap/Container';
import Image from 'react-bootstrap/Image';
import Card from 'react-bootstrap/Card';
import Row from 'react-bootstrap/Row';
import Col from 'react-bootstrap/Col';
import Button from 'react-bootstrap/Button';
import Media from 'react-bootstrap/Media';
import {useParams} from 'react-router-dom';
import {useSelector} from 'react-redux';
import { connect } from 'react-redux';
require('../styles/ChatApp.css');
const ChatApp = () => {
const [messages, setMessages] = React.useState([]);
const userId = useSelector(state => state.profile.profile._id);
const role = useSelector(state => state.profile.profile.role);
const addMessage = (message) => {
const messagess = [...messages];
messagess.push(message);
setMessages(messagess);
console.log(messagess);
}
const sendHandler = (message) => {
const messageObject = {
username: userId,
message
};
addMessage(messageObject);
}
return (
<div className="landing">
<Container>
<Row className="mt-5">
<Col md={{ span: 8, offset: 2 }}>
<Card style={{ height: "36rem" }} border="dark">
<Messages msgs={messages} />
<Card.Footer>
<ChatInput onSend={sendHandler}>
</ChatInput>
</Card.Footer>
</Card>
</Col>
</Row>
</Container>
</div>
)
};
ChatApp.defaultProps = {
username: 'anonymous'
};
const mapStateToProps = (state) => {
return {
authUser: state.auth.user,
profile: state.profile.profile
};
};
export default connect(
mapStateToProps
)(ChatApp);
Messages.js
import React from 'react';
import Message from './Message';
class Messages extends React.Component {
componentDidUpdate() {
// There is a new message in the state, scroll to bottom of list
const objDiv = document.getElementById('messageList');
objDiv.scrollTop = objDiv.scrollHeight;
}
render() {
// Loop through all the messages in the state and create a Message component
const messages = this.props.messages.map((message, i) => {
return (
<Message
key={i}
username={message.username}
message={message.message}
fromMe={message.fromMe} />
);
});
return (
<div className='messages' id='messageList'>
{ messages }
</div>
);
}
}
Messages.defaultProps = {
messages: []
};
export default Messages;
Message.js
import React from 'react';
import Image from 'react-bootstrap/Image'
import Media from 'react-bootstrap/Media';
class Message extends React.Component {
render() {
return (
<ul className="list-unstyled">
<Media as="li">
<Media.Body>
<h6 className="font-weight-bold">{ this.props.username }</h6>
<p>
{ this.props.message }
</p>
<p className="small text-muted">
3 hrs ago
</p>
</Media.Body>
</Media>
</ul>
);
}
}
Message.defaultProps = {
message: '',
username: '',
to: '',
fromMe: false
};
export default Message;

Related

React not rendering the array

I am new to react and trying to create a simple todo list to understand React states and props but cant seem to understand why its not rendering the array on the screen. When the button is pressed it console logs the array of the inputs so I know that works.
here is each component currently there are no errors just nothing shows up.
App.js:
import React from "react";
import ControlPanel from "./ControlPanel";
import TodoList from "./TodoList";
class App extends React.Component {
state = { TodoList: [] };
addTask = (todoItem) => {
this.setState({ TodoList: [...this.state.TodoList, todoItem] });
console.log(this.state.TodoList);
};
render() {
return (
<div>
<ControlPanel addTask={this.addTask} />
<TodoList todoitem={this.state.TodoList} />
</div>
);
}
}
export default App;
ControlPanel.js:
import React from "react";
class ControlPanel extends React.Component {
state = { todoItem: "" };
addItem = (event) => {
event.preventDefault();
this.props.addTask(this.state.todoItem);
};
render() {
return (
<div className="ui card">
<div className="ui input">
<input
onChange={(e) => {
this.setState({ todoItem: e.target.value });
}}
value={this.state.todoItem}
type="text"
placeholder="Todo List Item"
/>
</div>
<div>
<button onClick={this.addItem} className="ui button">
Add Item
</button>
</div>
</div>
);
}
}
export default ControlPanel;
TodoList.js:
import React from "react";
import TodoItem from "./TodoItem";
const TodoList = (props) => {
const todoItems = props.TodoList?.map((todo) => {
return <TodoItem TodoItem={TodoItem} />;
});
return <div>{todoItems}</div>;
};
export default TodoList;
TodoItem.js
import React from "react";
const TodoItem = (props) => {
return <div>{this.props.TodoItem}</div>;
};
export default TodoItem;
import React from "react";
import TodoItem from "./TodoItem";
const TodoList = (props) => {
const todoItems = props.TodoList?.map((todo,idx) => {
return <TodoItem TodoItem={todo} key={idx} />; // idx or any unique key
});
return <div>{todoItems}</div>;
};
export default TodoList;
More information for key
https://reactjs.org/docs/lists-and-keys.html

"Uncaught TypeError: loadAllFeedback is not a function" while trying dispatch an action in UseEffect()

I'm running into an issue where my action is not being recognized as a function in my useEffect(). I already checked to see if I was importing or dispatching incorrectly, but perhaps I'm missing something.
In my case, I want all of my feedback from the payload, so I don't need to pass anything specific through the action. I just want it to fetch the action when the feedback is empty.
import React, { useState, useEffect } from 'react';
import { withStyles } from '#material-ui/core/styles';
import PropTypes from 'prop-types';
import { connect, useSelector } from 'react-redux';
import { createStructuredSelector } from 'reselect';
import { requestFeedback } from 'common/state/feedback/actions';
import MUIDataTable from 'mui-datatables';
import { feedbackColumns } from 'components/DataTable/feedbackColumnHelper';
import Message from 'components/Message';
import ErrorMessage from 'components/ErrorMessage';
import { getIsUserAdmin } from 'common/state/auth/selectors';
import {
getFeedbackList,
getFeedbackErrorKey,
} from 'common/state/feedback/selectors';
import ParameterCrumbs from 'components/DataTable/Header/ParameterCrumbs';
import HelmetIoT from 'components/HelmetIoT';
import BreadCrumbs from 'components/Breadcrumbs';
import styles from './styles';
export const FeedbackPage = ({
userIsAdmin,
// timestamp,
feedbackErrorKey,
feedbackRows,
loadAllFeedback,
}) => {
const hasNoFeedbackLength = !feedbackRows?.length;
const feedbackViewData = useSelector((state) => getFeedbackList(state));
useEffect(() => {
if (hasNoFeedbackLength && !feedbackErrorKey) {
loadAllFeedback();
}
}, [hasNoFeedbackLength, feedbackErrorKey, loadAllFeedback]);
const tableOptions = {
draggableColumns: { enabled: true },
pagination: true,
rowsPerPage: 10,
print: false,
};
return (
<div>
<HelmetIoT preTitle={`Feedback Page `} />
<BreadCrumbs crumbs={[{ title: `Feedback Page` }]} />
<ParameterCrumbs />
{userIsAdmin && feedbackErrorKey && (
<div className="h-padding-t-default">
<ErrorMessage>There was an error loading feedback</ErrorMessage>
</div>
)}
{!feedbackErrorKey && userIsAdmin && (
<div className="h-padding-t-default">
<ErrorMessage>
You do not have permission to access this page
</ErrorMessage>
</div>
)}
{feedbackErrorKey && !userIsAdmin && (
<div className="h-padding-t-default">
<ErrorMessage>
There was an error loading feedback and you do not have permission
to access this page
</ErrorMessage>
</div>
)}
{!feedbackRows?.length && (
<div className="h-padding-t-default">
<Message>No feedback has been entered</Message>
</div>
)}
{!feedbackErrorKey && feedbackRows?.length && (
<MUIDataTable
title={'Feedback'}
data={feedbackViewData}
columns={feedbackColumns}
options={tableOptions}
/>
)}
</div>
);
};
FeedbackPage.propTypes = {
feedbackErrorKey: PropTypes.string,
feedbackRows: PropTypes.array,
loadAllFeedback: PropTypes.func,
};
const mapDispatchToProps = {
loadAllFeedback: requestFeedback,
};
const mapStateToProps = createStructuredSelector({
feedbackErrorKey: getFeedbackErrorKey,
feedbackRows: getFeedbackList,
userIsAdmin: getIsUserAdmin,
});
export default connect(
mapStateToProps,
mapDispatchToProps
)(withStyles(styles)(FeedbackPage));

React Redux --> UseSelector --> Not Working

I am trying to make a simple exercise for react-redux to understand the process but somehow I am stuck .. any help would be really appreciate.
The interesting part is when I do subscribe and try to log store into the console, it works and shows me updated value but I am not able to select it using useSelector
Also with the help of Dev tool's i could see the state being changed from INIT to ADD_USER..
Below are my components files and reducers.
App.js
import React from "react";
import { Provider } from "react-redux";
import store from "./stores/store";
import { HomePage } from "./components/containers/HomePage";
function App() {
return (
<Provider store={ store }>
<HomePage/>
</Provider>
);
}
export default App;
HomePage.js. --> Here state.isLogin is not selected.. but the subscribe comment works
import React from "react";
import { Sidebar } from "./Sidebar";
import { LoginPage } from "./LoginPage";
import { useSelector } from "react-redux";
export const HomePage = () => {
const userLogin = useSelector(state => state.isLogin);
// const storeState = store.subscribe (() => console.log(store.getState()));
return (
<div>
<LoginPage />
<Sidebar />
</div>
);
};
LoginPage.js
import React, { useState } from "react";
import { useDispatch } from "react-redux";
import * as action from "../../action/index";
export const LoginPage = (setLogin) => {
const dispatch = useDispatch();
const [name, setName] = useState("");
const createUser = (e) => {
e.preventDefault();
const addUser = {
name: name,
isLogin: true
};
dispatch(action.addUsers(addUser));
};
return (
<div className="card border-0 shadow">
<div className="card-header">Login Here!</div>
<div className="card-body">
<form onSubmit={(e) => createUser(e)}>
<div className="form-group">
<input
type="text"
className="form-control"
placeholder="Enter Your Name"
value={name}
onChange={(e) => setName(e.target.value)}
/>
</div>
<button className="btn btn-primary" type="submit">
Create Contact
</button>
</form>
</div>
</div>
);
};
reducers - Index.js and user.js
import userReducer from './users'
import { combineReducers} from "redux";
const allReducers = combineReducers({
addUser : userReducer,
});
export default allReducers;
User.js
import * as types from '../actionTypes/index'
const intialState = {
user: [],
messages : [],
isLogin : false
};
const users = (state = intialState, action) => {
switch (action.type) {
case types.ADD_USER:
return {
...state,
user: [action.payload.name, ...state.user],
isLogin: action.payload.isLogin
};
default:
return state
}
}
export default users;
Store.js
import { createStore } from "redux";
import { composeWithDevTools } from "redux-devtools-extension";
import allReducers from '../reducers'
const store = createStore(allReducers,composeWithDevTools());
export default store;
Any idea's/Input on what went wrong ? or what is the issue?
Thank you
Try using below code in HomePage
const userLogin = useSelector(state => state.addUser.isLogin);

React Props for Handle Change not a Function

I'm getting props.handleChange is not a function when running the following code. I'm trying to update the state when the checkbox is clicked. The field that is check box is called myNetwork. I thought that when NetworkArray component, which is a parent of Card component, would have access to the functions and state in App? But this is my first React App. Please, what am I doing wrong?
App.JS
import React, {Component} from 'react';
import SignUp from './components/SignUp';
import NetworkArray from './components/NetworkArray';
import {network} from './NetworkData'
import './App.css';
import 'tachyons';
class App extends Component {
constructor() {
super()
this.state = {
network: network,
}
this.handleChange=this.handleChange.bind(this);
}
handleChange(id) {
this.setState(prevState => {
const updatedNetwork = prevState.network.map(netw => {
if (netw.id===id) {
netw.myNetwork = !netw.myNetwork
}
return netw
})
return {
network:updatedNetwork
}
})
}
render() {
return (
<div>
<NetworkArray
network={network}
handleChange = {this.handleChange} />
</div>
);
}
}
export default App;
Card.js
import React from 'react';
const Card = (props) => {
return(
<div className = 'bg-light-green dib br3 pa3 ma2 grow shadow-5'>
<div>
<h3>{props.name}</h3>
<p>{props.company}</p>
<p>{props.phone}</p>
<p>{props.email}</p>
<p>{props.city}</p>
</div>
<div>
MyNetwork
<input
type = "checkbox"
checked={props.myNetwork}
onChange={()=> props.handleChange(props.id)}
/>
</div>
</div>
)
}
export default Card;
NetworkArray.js
import React, {Component} from 'react';
import Card from './Card';
const NetworkArray = ({network}) => {
const cardComponent = network.map((user,i) => {
return(
<Card
key = {network[i].id}
name = {network[i].firstName + ' ' + network[i].lastName}
company = {network[i].company}
phone= {network[i].phone}
email={network[i].email}
city = {network[i].city}
/>
)
})
return (
<div>
{cardComponent}
</div>
)
}
export default NetworkArray;
You passed the function from App component to NetworkArray component, but not to Card component.
const NetworkArray = ({network, handleChange}) => {
...
<Card
handleChange={handleChange}
...
/>
}

Material UI React Test cases failing - JEST, ENZYME

I have a connected component and have integrated MaterialUI in my component. For some reason, the tests keep on failing and I am not able to find some article online to resolve this.
Please advice.
Below is my code.
import React, {Component} from 'react';
import {connect} from 'react-redux';
import SourceCurrencyInput from './components/SourceCurrencyInput';
import TargetCurrencyInput from './components/TargetCurrencyInput';
import {fetchCurrencyConverterRates} from './actions/currencyConverterActions';
import CurrencyConverterValue from './components/CurrencyConverterValue';
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 {withStyles} from '#material-ui/core/styles';
import './App.css';
import {
changeSourceCurrencyValue,
changeTargetCurrencyValue
} from './actions/actions';
const styles = {
root: {
flexGrow: 1,
},
grow: {
flexGrow: 1,
},
menuButton: {
marginLeft: -12,
marginRight: 20,
},
};
class App extends Component {
componentDidMount() {
this.props.fetchCurrencyConverterRates(
this.props.srcCurrencyType,
this.props.tgtCurrencyType
);
}
componentDidUpdate(prevProps, prevState, snapshot) {
if (prevProps.srcCurrencyType !== this.props.srcCurrencyType
|| prevProps.tgtCurrencyType !== this.props.tgtCurrencyType) {
this.props.fetchCurrencyConverterRates(
this.props.srcCurrencyType,
this.props.tgtCurrencyType);
}
}
clearAll = () => {
this.props.sourceValue('');
this.props.targetValue('');
};
render() {
const {srcCurrencyType, tgtCurrencyType, srcCurrencyValue, tgtCurrencyValue, currencyConversionRate, classes} = this.props;
return (
<div className="App">
<AppBar position="static">
<Toolbar>
<Typography variant="h6" color="inherit" className={classes.grow}>
Currency Converter by Arun Manohar
</Typography>
</Toolbar>
</AppBar>
<header className="App-header">
<SourceCurrencyInput/>
<TargetCurrencyInput/>
<Button variant="contained" color="primary" className={classes.button}
onClick={() => this.clearAll()}>Clear</Button>
</header>
<CurrencyConverterValue srcCurrencyType={srcCurrencyType}
tgtCurrencyType={tgtCurrencyType}
srcCurrencyValue={srcCurrencyValue}
tgtCurrencyValue={tgtCurrencyValue}
currencyConversionRate={currencyConversionRate}
/>
<footer><a href={'https://currencyconverterapi.com'} target={'_blank'}>API from currencyconverterapi.com</a></footer>
</div>
);
}
}
const mapStateToProps = state => {
return {
srcCurrencyType: state.currencyConverterReducer.sourceCurrencyType,
tgtCurrencyType: state.currencyConverterReducer.targetCurrencyType,
srcCurrencyValue: state.currencyConverterReducer.sourceCurrencyValue,
tgtCurrencyValue: state.currencyConverterReducer.targetCurrencyValue,
currencyConversionRate: state.getConvertedRates.data[0]
};
};
const mapDispatchToProps = (dispatch) => ({
fetchCurrencyConverterRates: (src, tgt) => dispatch(fetchCurrencyConverterRates(src, tgt)),
sourceValue: (val) => dispatch(changeSourceCurrencyValue(val)),
targetValue: (val) => dispatch(changeTargetCurrencyValue(val)),
});
export default connect(mapStateToProps, mapDispatchToProps)(withStyles(styles)(App));
Below is my test case.
import React from 'react';
import {Provider} from 'react-redux';
import configureStore from 'redux-mock-store';
import App from './App';
import {createMount} from '#material-ui/core/test-utils';
const mockStore = configureStore();
const initialState = {sourceCurrencyType: 'USD'};
const store = mockStore(initialState);
describe('<App />', () => {
let mount;
beforeEach(() => {
mount = createMount();
});
it('should work', () => {
const wrapper = mount(<Provider store={store}><App/></Provider>);
console.log(wrapper.debug());
});
});
This is the error I get.
TypeError: Cannot read property 'sourceCurrencyType' of undefined
I just need a way to access this component in my tests. Please help me out.
Your initial state must keep the same structure with the reducer object, such:
const initialState = {
currencyConverterReducer: {
sourceCurrencyType: 'USD',
// rest of attributes of currencyConverterReducer
}
};

Categories