I was trying to build simple react-redux app using reducers. But every time I open the website it is popping up this error and I couldn’t open the console. I tried to clean cookies and caches but no help.
Whenever I change <Posts />
and <Form />
to simple <h1>
tags it works perfectly fine, but I can’t find the bug.
My code in
index.js:
import React from 'react'; import ReactDOM from 'react-dom'; import { Provider } from 'react-redux'; import { createStore, applyMiddleware, compose } from 'redux'; import thunk from 'redux-thunk'; import { reducers } from './reducers/index.js'; import App from './App'; const store = createStore(reducers, compose(applyMiddleware(thunk))); ReactDOM.render( <Provider store={store}> <App /> </Provider>, document.getElementById('root'), );
App.js
import React,{ useEffect, useState } from 'react'; import { Container, AppBar, Typography, Grid, Grow } from '@material-ui/core'; import { useDispatch } from 'react-redux'; import Posts from '../src/components/Posts'; import Form from './components/form'; import { getPosts } from './actions/action'; function App() { const [currentId, setCurrentId] = useState(); const dispatch = useDispatch(); useEffect(() =>{ dispatch(getPosts()); },[dispatch, currentId]); return ( <div> <Container maxWidth='lg'> <AppBar position='static' color='inherit'> <Typography variant='h2' align='center' >SimplePRATICE</Typography> </AppBar> <Grow in> <Container> <Grid container justify='space-between' alignItems='stretch' spacing={3}> <Grid item xs={12} sm={4}> <Form currentId={currentId} setCurrentId={setCurrentId} /> </Grid> </Grid> </Container> </Grow> </Container> </div> ); } export default App;
form.js
import React, { useEffect, useState } from 'react'; import { Paper, Button, TextField, Typography } from '@material-ui/core'; import { useSelector, useDispatch } from 'react-redux'; import { createPost, updatePost } from '../actions/action.js'; function Form({ currentId, setCurrentId }) { const [postData, setpostData] = useState({ name:'', message:'' }); const post = useSelector((state) => (currentId ? state.posts.find((message) => message._id === currentId ) :null )); const dispatch = useDispatch(); useEffect(() => { if (post) setpostData(post); }, [post]); const clear = () =>{ setCurrentId(0); setpostData({ name: '', message:''}); }; const handleSubmit = async (e) => { e.preventDefault(); if (currentId === 0){ dispatch(createPost(postData)); }else{ dispatch(updatePost(currentId, postData)); } clear(); }; return ( <Paper> <Form onSubmit={handleSubmit}> <Typography>Creating Post</Typography> <TextField name="name" variant="outlined" label="Name" fullWidth value={postData.name} onChange={(e) => setpostData({ ...postData, name: e.target.value })} /> <TextField name="message" variant="outlined" label="Message" fullWidth multiline rows={4} value={postData.message} onChange={(e) => setpostData({ ...postData, message: e.target.value })} /> <Button varient='contained' color='primary' size='large' type='submit' fullWidth>Submit</Button> </Form> </Paper> ) } export default Form
Posts.js
import React from 'react'; import Post from './post.js'; import { Grid } from '@material-ui/core'; import { useSelector } from 'react-redux'; function Posts({ setCurrentId }) { const posts = useSelector((state) => state.posts); return ( <Grid container alignItems='stretch' spacing={3}> {posts.map((post) => ( <Grid key={post._id} item xs={12} sm={6} md={6}> <Post post={post} setCurrentId={setCurrentId} /> </Grid> ))} </Grid> ) } export default Posts
Post.js
import React from 'react'; import { Card, CardActions, CardContent, Button, Typography } from '@material-ui/core/'; import DeleteIcon from '@material-ui/icons/Delete'; import MoreHorizIcon from '@material-ui/icons/MoreHoriz'; import { useDispatch } from 'react-redux'; import { deletePost } from '../actions/action.js'; function Post({ post, setCurrentId }) { const dispatch = useDispatch(); return ( <Card> <div> <Typography varient='h6'>{post.name}</Typography> </div> <di> <Button style={{ color:'white' }} size='small' onClick={()=> setCurrentId(post._id)}><MoreHorizIcon fontSize='default' /></Button> </di> <CardContent> <Typography vaarient='body2' color='textSecondary' component='p'>{post.message}</Typography> </CardContent> <CardActions> <Button size='small' color='primary' onClick={()=> dispatch(deletePost(post._id))} ><DeleteIcon fontSize='small'>Delete</DeleteIcon></Button> </CardActions> </Card> ) } export default Post
import axios from 'axios'; const url = 'http://localhost:5000/posts'; export const fetchPosts = () => axios.get(url); export const createPost = (newPost) => axios.post(url, newPost); export const updatePost = (id, updatedPost) => axios.patch(`${url}/${id}`, updatedPost); export const deletePost = (id) => axios.delete(`${url}/${id}`);
Advertisement
Answer
Your Form
component renders itself:
return ( <Paper> <Form onSubmit={handleSubmit}> <Typography>Creating Post</Typography> <TextField name="name" variant="outlined" label="Name" fullWidth value={postData.name} onChange={(e) => setpostData({ ...postData, name: e.target.value })} /> <TextField name="message" variant="outlined" label="Message" fullWidth multiline rows={4} value={postData.message} onChange={(e) => setpostData({ ...postData, message: e.target.value })} /> <Button varient='contained' color='primary' size='large' type='submit' fullWidth>Submit</Button> </Form> </Paper> )
I think you meant <form>
which is not a react component.
return ( <Paper> <form onSubmit={handleSubmit}> <Typography>Creating Post</Typography> <TextField name="name" variant="outlined" label="Name" fullWidth value={postData.name} onChange={(e) => setpostData({ ...postData, name: e.target.value })} /> <TextField name="message" variant="outlined" label="Message" fullWidth multiline rows={4} value={postData.message} onChange={(e) => setpostData({ ...postData, message: e.target.value })} /> <Button varient='contained' color='primary' size='large' type='submit' fullWidth>Submit</Button> </form> </Paper> )