In my file called app.jsx i have one import from the component "atividades":
import React from 'react'
import { Container } from 'semantic-ui-react'
import atividades from '../atividades/atividades'
export default props => (
<Container>
<h1>Teste</h1>
<atividades />
</Container>
)
But only the h1 is rendering...
This is my atividades component:
import React, { Component } from 'react'
import { connect } from 'react-redux'
import { bindActionCreators } from 'redux'
import { Form } from 'semantic-ui-react'
import { addWorkout, searchWorkout } from './workOutActions'
import { Button, Icon } from 'semantic-ui-react'
const workoutOptions = [
{ text: 'correr', value: 'run' },
{ text: 'nadar', value: 'swimming' },
{ text: 'andar de bicicleta', value: 'bike' },
]
class atividades extends Component {
constructor(props){
super(props)
}
componentWillMount(){
this.props.searchWorkout()
}
render() {
const { addWorkout, searchWorkout, tempoGasto, tipoTarefa, data} = this.props
return (
<div role='form'>
<h6>Inserir atividade</h6>
<Form>
<Form.Group widths='equal'>
<Form.Input fluid placeholder='Tempo gasto' />
<Form.Select
fluid
label='Atividade'
options={workoutOptions}
/>
<Button animated='vertical'>
<Button.Content hidden>Shop</Button.Content>
<Button.Content visible>
<Icon name='shop' />
</Button.Content>
</Button>
</Form.Group>
</Form>
</div>
)
}
}
const mapStateToProps = state => ({tempoGasto: state.workout.tempoGasto, tipoTarefa: state.workout.tipoTarefa, data: state.workout.data})
const mapDispatchToProps = dispatch =>
bindActionCreators({ addWorkout, searchWorkout }, dispatch)
export default connect(mapStateToProps, mapDispatchToProps)(atividades)
It's not showing nothing in the console, but the element workout is not rendering, the visual studio code says that the import is not being used.
The first letter of React components must be capitalized or it thinks it’s a built in component like div or p or span.
This link has more info:
ReactJS component names must begin with capital letters?
Related
I am writing a test for a component that is wrapped in a withStyles() from Material UI using Jest. I have searched many examples but didn't get solution.
Below are the my files:
Login.js
import React, { Component } from 'react';
import { connect } from 'react-redux';
import * as Actions from 'auth/store/actions/index';
import { bindActionCreators } from 'redux';
import { withRouter } from 'react-router-dom';
import { withStyles } from '#material-ui/core/styles/index';
import { TextFieldFormsy } from '#fuse';
import Formsy from 'formsy-react';
import {
Button, Card, CardContent, Typography,
} from '#material-ui/core';
const styles = () => ({
card: {
width: '100%',
maxWidth: 400,
},
});
class Login extends Component {
state = {
email: '',
password: '',
};
form = React.createRef();
componentDidMount() {
this.props.resetErrorMessage();
}
componentDidUpdate() {
}
onSubmit = (model) => {
this.props.submitMerritosLogin(model);
};
render() {
const { classes } = this.props;
const { email, password } = this.state;
return (
<Card className={`${classes.card} mx-auto md:m-0 merritos-login-card merritos-mobile-register
justify-center items-center flex flex-col`}>
<CardContent className="flex flex-col p-44">
<img className="w-256 mb-32 ml-6 merritos-desktop-display merritos-mobile-image merritos-mobile-images self-center" src="assets/images/logos/merritos-blue-small.png" alt="logo" />
<Typography className="mt-16 font-bold text-24 merritos-login-subtitile merritos-theme-colour">Sign in</Typography>
<Typography className="mb-56 text-grey-darker text-16 font-bold ">to your professional world</Typography>
<Formsy
onValidSubmit={this.onSubmit}
ref={form => this.form = form}
className="flex flex-col justify-center w-full merritos-form"
>
<TextFieldFormsy
className="mb-16 merritos-border-color merritos-accountinfo-textinput"
type="email"
name="email"
label="Email"
value={email}
required
/>
<TextFieldFormsy
className="mb-16 merritos-border-color merritos-accountinfo-textinput"
type="password"
name="password"
label="Password"
value={password}
required
/>
<Button
color="primary"
size="small"
type="submit"
className="text-16 normal-case merritos-login-btn accountinfo-margin"
aria-label="LOG IN"
>
Sign in
</Button>
</Formsy>
</CardContent>
</Card>
);
}
}
function mapDispatchToProps(dispatch) {
return bindActionCreators({
submitMerritosLogin: Actions.submitMerritosLogin,
resetErrorMessage: Actions.resetErrorMessage,
}, dispatch);
}
function mapStateToProps({ auth }) {
return {
user: auth.user,
};
}
export default withStyles(styles, { withTheme: true })(withRouter(
connect(mapStateToProps, mapDispatchToProps)(Login),
));
login.test.js
import React from 'react';
import {render, fireEvent, screen} from '#testing-library/react';
import { shallow } from 'enzyme';
import Login from './Login';
describe('login', () => {
test('renders without crashing', () => {
const wrapper = shallow(<Login.WrappedComponent />);
expect(wrapper.find('Button').text()).toEqual('Sign in');
});
});
While running test I am getting error like bellow:
login › renders without crashing
TypeError: Cannot read property 'card' of undefined
I removed the classes.card and tried then also I got error below:
login › renders without crashing
TypeError: Cannot read property 'resetErrorMessage' of undefined
I am wanting the wrapper component to behave the same way as a wrapper without the withStyles() component.
Looks like you are testing the wrapped component without passing any props while the component requires some props having to be passed.
I think it would work as you pass some needed props to it, it would work as following:
Export Login class in your Login.js
export class Login {
// ...
}
Then import to the test:
// you should import `Login` class to test separately
import { Login } from "./Login";
test('renders without crashing', () => {
const props = {
classes: {
card: 'yourCardClass',
},
resetErrorMessage: jest.fn(),
submitMerritosLogin: jest.fn(),
};
const wrapper = shallow(<Login {...props} />);
// should get called as component did mount
expect(props.resetErrorMessage).toHaveBeenCalled();
expect(wrapper.find('Button').text()).toEqual('Sign in');
});
Very Simple code , I'hv checked react spelling, ReactDom imported, Please guide me about the error. I am new to the codding world.
import React, { Component } from "react";
import "./App.css";
import { Cardlist } from "./components/cardlist/cardlist.component.jsx";
class App extends Component {
constructor() {
super();
this.state = {
string: "Hello before",
};
}
render() {
return (
<div className="App">
<p>{this.state.string}</p>
<button onClick={() => this.setState({ string: "After text" })}>
Change text
</button>
<Cardlist name="this was prop" />
</div>
);
}
}
export default App;
Cardlist component
import react from "react";
export const Cardlist = (props) => {
console.log(props);
return <div>COngratulations</div>;
};
Try changing that react to React on first line on CardList ?
I am going to post my question here and hopefully learn something! I've been following a tutorial and do not yet have the insight into React and Redux to effectively figure out what is going on. I want to create functionality that adds and removes businesses to global state in React and Redux. From what I've Googled I know the file structures vary depending on the project so I will post all of my files here. I have them divided into actions.js, reducers.js, state.js, and store.js. I have an add Listing view with React and would like to add remove functionality to my view listings view. Here are my files:
redux/actions.js:
export const addListing = (newBusiness) => {
return {
type: 'ADD_LISTING',
value: newBusiness
}
}
export const removeListing = (index) => {
return {
type: 'REMOVE_LISTING',
value: index
}
}
redux/reducers.js:
import { combineReducers } from 'redux';
import { addBusiness, removeBusiness } from './actions'
const user = (state = null) => state
// add switch statements in here
const businesses = (state = [], action) => {
switch(action.type) {
case 'ADD_BUSINESS':
return [ ...state, action.value ]
case 'REMOVE_BUSINESS':
const newState = [ ...state ]
newState.splice(action.value, 1);
return newState;
default: // need this for default case
return state
}
}
export default combineReducers({ user, businesses })
redux/state.js
export default {
user: {
username: 'test-user-1',
email: 'test-user#example.com'
},
businesses: [
{
"id": 15,
"name": "My pizza",
"description":"Homemade pizza shop",
"address": "123 Taco Street",
"hours": "9-5"
}
]
};
redux/store.js
import { createStore } from 'redux'
import reducers from './reducers'
import state from './state'
export default createStore(reducers, state)
containers/addListing.js
import { connect } from "react-redux";
import { addListing } from '../redux/actions';
import AddListing from '../components/addListing'
const mapDispatchToProps = (dispatch) => {
return {
addListing: (business) => dispatch(addListing(business)),
}
}
export default connect(null, mapDispatchToProps)(AddListing)
containers/removeListing.js
import { connect } from "react-redux";
import { removeListing } from '../redux/actions';
const mapDispatchToProps = (dispatch) => {
return {
removeCar: (business) => dispatch(removeListing(business)),
}
}
export default connect(null, mapDispatchToProps)(removeListing)
containers/Listing.js:
import { connect } from 'react-redux'
import Listing from '../components/Listing'
const mapStateToProps = (state) => {
return {
businesses: state.businesses,
user: state.user.username
}
}
export default connect(mapStateToProps)(Listing)
components/addListing.js
import React from 'react';
import { InputLabel } from '#material-ui/core'
import { Input } from '#material-ui/core'
import { FormControl } from '#material-ui/core';
import { Button } from '#material-ui/core';
import { TextField } from '#material-ui/core';
import '../redux/state';
class addListing extends React.Component {
state = {
name: '',
description: '',
address: '',
hours: ''
}
handleTextChange = (e) => {
const newState = { ...this.state }
newState[e.target.id] = e.target.value
this.setState(newState)
console.log(this.state)
}
handleSubmit = (e) => {
e.preventDefault()
const payload = { ...this.state }
console.log("THE BUSINESS", payload)
this.props.addListing(payload)
console.log(this.props)
}
componentDidUpdate = (prevProps, prevState) => {
if (prevState.open !== this.state.open) {
this.setState({
name: '',
description: '',
address: '',
hours: ''
})
}
}
render(){
return (
<div className="App">
<form
onSubmit={this.handleSubmit}
style={{ display: 'flex', flexDirection: 'column', width: '350px' }}>
<TextField
id="name"
name="name"
placeholder="Name"
value={this.state.name}
onChange={this.handleTextChange}
required />
<TextField
id="description"
name="description"
placeholder="Description"
value={this.state.description}
onChange={this.handleTextChange}
required />
<TextField
id="address"
name="address"
placeholder="Address"
value={this.state.address}
onChange={this.handleTextChange}
required />
<TextField
id="hours"
name="hours"
placeholder="Hours"
value={this.state.hours}
onChange={this.handleTextChange}
required />
<br />
<Button variant="contained" color="primary" type="submit">Submit</Button>
</form>
</div>
);
}
}
export default addListing;
components/Listing.js:
import React from 'react'
import {
Container,
Table,
TableBody,
TableCell,
TableHead,
TableRow
} from '#material-ui/core'
import DeleteIcon from '#material-ui/icons/Delete'
import addListing from '../containers/addListing'
import removeListing from '../containers/removeListing'
import businesses from '../redux/state'
import user from '../redux/state';
const Listing = (props) => {
console.log(props.businesses)
return (
<Container maxWidth="lg" className="car-container">
<h4>Welcome, {props.user.username}</h4>
<div className="flex-container">
</div>
<Table>
<TableHead>
<TableRow>
<TableCell>ID</TableCell>
<TableCell>Name</TableCell>
<TableCell>Description</TableCell>
<TableCell>Address</TableCell>
<TableCell>Hours</TableCell>
</TableRow>
</TableHead>
<TableBody>
{props.businesses.map((businesses, idx) => (
<TableRow key={businesses.id}>
<TableCell component="th" scope="row">
</TableCell>
<TableCell>{businesses["name"]}</TableCell>
<TableCell>{businesses["description"]}</TableCell>
<TableCell>{businesses["address"]}</TableCell>
<TableCell>{businesses["hours"]}</TableCell>
<TableCell>
<DeleteIcon
// add onClick method here
// onClick={props.removeCar(idx)}
className="icon text-red"
onClick={ () => this.props.removeListing(idx)}
/>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</Container>
)
}
export default Listing
App.js:
import React from 'react';
import Navigation from './components/Navigation'
import './App.css'
import Router from './Router'
import { BrowserRouter } from 'react-router-dom'
import { Provider } from 'react-redux'
import store from './redux/store'
function App() {
return (
<Provider store={store}>
<BrowserRouter>
<Navigation />
<Router />
</BrowserRouter>
</Provider>
);
}
export default App;
index.js:
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import Login from './components/Login'
import App from './App';
import * as serviceWorker from './serviceWorker';
import Listing from '../src/components/Listing';
import { Provider } from 'react-redux';
ReactDOM.render(
<App />,
document.getElementById('root')
);
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
serviceWorker.unregister();
So far I know it's something simple. I am getting no errors but it just doesn't seem to add the new listings to global state. When I get to the listing view it only displays the Business I included as a default in state.js. I will try to reply in a quick manner and please let me know if more info is needed. Thanks!
I see that the names of your actions are different ADD_LISTING vs ADD_BUSINESS, REMOVE_LISTING vs. REMOVE_BUSINESS.
In the addListing you have {type: 'ADD_LISTING', ...}, in your reducer you have case 'ADD_BUSINESS': The strings are different. They need to match. Try renaming ADD_BUSINESS => ADD_LISTING, and REMOVE_BUSINESS=>REMOVE_LISTING.
Regarding the crash on line 50. You don't need this. because your component is not a class type. Change it to onClick={ () => props.removeListing(idx)}.
You're missing removeListing in the mapDispatchToProps.
Also, Redux DevTools plugin for Chrome can help you a lot in debugging issues with redux..
I want to make an app so that when text is typed in input element this will reflect that change in output. So far the updating doesn't work :(
import React, { Component } from 'react';
import './App.css';
import UserInput from './UserInput/UserInput';
import UserOutput from './UserOutput/UserOutput';
class App extends Component {
state = {
user: [
{ username: 'Kai' },
{ username: 'Orange' }
]
}
inputChangeHandler = (e) => {
this.setState(
{
user: [
{ username: e.target.value },
{ username: e.target.value }
]
}
)
}
render() {
return (
<div className="App">
<UserInput onChange={this.inputChangeHandler} />
<UserOutput username={this.state.user[0].username} />
<UserOutput username={this.state.user[1].username} />
</div>
);
}
}
export default App;
Change in text typed in input element should be reflected as username rendered in UserOutput. This doesn't work.
Here are codes for other components...
import React, { Component } from 'react';
class UserInput extends Component
{
render() {
return(
<div>
<input />
</div>
);
}
}
export default UserInput;
and
import React, { Component } from 'react';
class UserOutput extends Component
{
render() {
return(
<div>
<p>First paragraph and my name is {this.props.username}</p>
<p>Second paragraph </p>
</div>
);
}
}
export default UserOutput;
Ok there's your problem. You're not assigning the change handler to the input element in your UserInput component. It should be:
<input onChange={this.props.onChange} />
I'm trying to insert a personalized theme into my component, however when using console.log() in properties in styles I get a return that the object is empty.
I do not get any kind of error warning, why is this happening?
// LIBRARY AND MODULES
import React from "react";
// STYLES
import GlobalStyle from "../../styles/global";
import { ContainerPage, FooterContainerPage, FormElement } from "./styles";
// COMPONENTS
import CardRepository from "../../components/stateless/specifics/Cards/Repository/Repository";
import Input from "../../components/stateless/generics/Input/Input";
import Button from "../../components/stateless/generics/Button/Button";
const themes = {
buttons: {
searchRepository: {
bgColor: "#73c894",
txtColor: "#ffffff",
hoverBgColor: "#218838"
}
}
};
export default class App extends React.Component {
state = {
buttonIsDisabled: false
};
searchRepository() {
alert("ae");
}
render() {
const { buttonIsDisabled } = this.state;
return (
<React.Fragment>
<GlobalStyle />
<FooterContainerPage>
<FormElement>
<Button
theme={themes.buttons.searchRepository}
type="button"
onClick={this.searchRepository}
disabled={buttonIsDisabled}
required={true}
>
BUSCAR
</Button>
</FormElement>
</FooterContainerPage>
</React.Fragment>
);
}
}