i've a component that i import, but its not displayed on the page.
this is my app.js file. i imported the <LineGraph/>component but it is not getting displayed properly on the browser.
import React, { useEffect, useState } from "react";
import {
MenuItem,
FormControl,
Select,
Card,
CardContent,
} from "#material-ui/core";
import InfoBox from "./infoBox";
import Table from "./table";
import "./App.css";
import { sortData } from "./util";
import LineGraph from "./LineGraph";
const App = () =\> {
const \[countries, setCountries\] = useState(\[\]);
const \[country, setCountry\] = useState("worldwide");
const \[countryInfo, setCountryInfo\] = useState({});
const \[tableData, setTableData\] = useState(\[\]);
const \[casesType, setCasesType\] = useState("cases");
useEffect(() =\> {
fetch("https://disease.sh/v3/covid-19/all")
.then((response) =\> response.json())
.then((data) =\> {
setCountryInfo(data);
});
}, \[\]);
useEffect(() =\> {
const getCountriesData = async () =\> {
fetch("https://disease.sh/v3/covid-19/countries")
.then((response) =\> response.json())
.then((data) =\> {
const countries = data.map((country) =\> ({
name: country.country,
value: country.countryInfo.iso2,
}));
const sortedData = sortData(data);
setTableData(sortedData);
setCountries(countries);
});
};
getCountriesData();
}, \[\]);
const onCountryChange = async (event) =\> {
const countryCode = event.target.value;
console.log("s", countryCode);
setCountry(countryCode);
const url =
countryCode === "worldwide"
? "https://disease.sh/v3/covid-19/all"
: `https://disease.sh/v3/covid-19/countries/${countryCode}`;
await fetch(url)
.then((response) => response.json())
.then((data) => {
setCountry(countryCode);
setCountryInfo(data);
});
};
console.log("CuntryInfo: ", countryInfo);
return (
\<div className="App"\>
\<div className="app__left"\>
\<div className="app__header"\>
\<h1\>COVID-19 Tracker\</h1\>
\<FormControl className="app__dropdown"\>
\<Select
variant="outlined"
onChange={onCountryChange}
value={country}
\\>
\<MenuItem value="worldwide"\>Worldwide\</MenuItem\>
{countries.map((country) =\> (
\<MenuItem value={country.value}\>{country.name}\</MenuItem\>
))}
\</Select\>
\</FormControl\>
\</div\>
<div className="app__stats">
<InfoBox
title="Coronavirus cases"
cases={countryInfo.todayCases}
total={countryInfo.cases}
/>
<InfoBox
title="Recovered"
cases={countryInfo.todayRecovered}
total={countryInfo.recovered}
/>
<InfoBox
title="Deaths"
cases={countryInfo.todayDeaths}
total={countryInfo.deaths}
/>
</div>
</div>
<Card className="app__right">
<CardContent>
{/* Table */}
<h3>Live Cases by country</h3>
<Table countries={tableData} />
{/* Graph */}
<h3>Word Wide New </h3>
<LineGraph casesType={casesType} />
</CardContent>
</Card>
</div>
);
};
export default App;
and My content of LineGraph.js :
import React, { useState, useEffect } from "react";
import { Line } from "react-chartjs-2";
import numeral from "numeral";
const options = {
legend: {
display: false,
},
elements: {
point: {
radius: 0,
},
},
maintainAspectRatio: false,
tooltips: {
mode: "index",
intersect: false,
callbacks: {
label: function (tooltipItem, data) {
return numeral(tooltipItem.value).format("+0,0");
},
},
},
};
const buildChartData = (data, casesType) => {
let chartData = [];
let lastDataPoint;
for (let date in data.cases) {
if (lastDataPoint) {
let newDataPoint = {
x: date,
y: data[casesType][date] - lastDataPoint,
};
chartData.push(newDataPoint);
}
lastDataPoint = data[casesType][date];
}
return chartData;
};
function LineGraph({ casesType }) {
const [data, setData] = useState({});
useEffect(() => {
const fetchData = async () => {
await fetch("https://disease.sh/v3/covid-19/historical/all?lastdays=120")
.then((response) => {
return response.json();
})
.then((data) => {
let chartData = buildChartData(data, casesType);
setData(chartData);
console.log(chartData);
// buildChart(chartData);
});
};
fetchData();
}, [casesType]);
return (
<div>
{data?.length > 0 && (
<Line
data={{
datasets: [
{
backgroundColor: "rgba(204, 16, 52, 0.5)",
borderColor: "#CC1034",
data: data,
},
],
}}
options={options}
/>
)}
</div>
);
}
export default LineGraph;
When I import the LineGraph.js component in the App.js file, the output is not displayed without any error.
in console error is :
react-dom.development.js:25830
Uncaught Error: "category" is not a registered scale.
Related
I am dispatching an action that is supposed to take an input from the user and store it in a database. However, when I inspect my posts state in redux after the action is dispatched, there is a null value appended to the state array before the actual post. This is preventing me from working with the actual data in the posts array. Basically I'm wondering how to prevent null from being appended each time I dispatch a new post. Here are the relevant code snippets and images.
Post Reducer:
import { enableAllPlugins, produce } from 'immer';
enableAllPlugins();
const initialState = {
posts: [],
loading: false,
error: false,
uploading: false,
};
const postReducer = produce((draftstate, action = {}) => {
switch (action.type) {
case 'UPLOAD_START':
draftstate.loading = true;
draftstate.error = false;
case 'UPLOAD_SUCCESS':
draftstate.posts.push(action.data);
draftstate.uploading = false;
draftstate.error = false;
case 'UPLOAD_FAIL':
draftstate.uploading = false;
draftstate.error = true;
default:
return draftstate;
}
}, initialState);
export default postReducer;
Upload Post action:
export const uploadPost = (data) => async (dispatch) => {
dispatch({ type: 'UPLOAD_START' });
try {
const newPost = await UploadApi.uploadPost(data);
console.log('new post before', newPost);
dispatch({ type: 'UPLOAD_SUCCESS', data: newPost.data });
} catch (error) {
console.log(error);
dispatch({ type: 'UPLOAD_FAIL' });
}
};
Share Post code:
import React, { useState, useRef } from "react";
import ProfileImage from "../../img/profileImg.jpg";
import "./PostShare.css";
import { UilScenery } from "#iconscout/react-unicons";
import { UilPlayCircle } from "#iconscout/react-unicons";
import { UilLocationPoint } from "#iconscout/react-unicons";
import { UilSchedule } from "#iconscout/react-unicons";
import { UilTimes } from "#iconscout/react-unicons";
import { useSelector, useDispatch } from "react-redux";
import { uploadImage, uploadPost } from "../../actions/uploadAction";
const PostShare = () => {
const loading = useSelector((state) => state.postReducer.uploading);
const [image, setImage] = useState(null);
const imageRef = useRef();
const desc = useRef();
const dispatch = useDispatch();
const { user } = useSelector((state) => state.authReducer.authData);
// handle Image Change
const onImageChange = (event) => {
if (event.target.files && event.target.files[0]) {
let img = event.target.files[0];
setImage(img);
}
};
const reset = () => {
setImage(null);
desc.current.value = "";
};
const handleSubmit = async (e) => {
e.preventDefault();
const newPost = {
userId: user._id,
desc: desc.current.value,
};
if (image) {
const data = new FormData();
const filename = Date.now() + image.name;
data.append("name", filename);
data.append("file", image);
newPost.image = filename;
console.log(newPost);
try {
dispatch(uploadImage(data));
} catch (error) {
console.log(error);
}
}
dispatch(uploadPost(newPost));
reset();
};
return (
<div>
<div className="PostShare">
<img src={ProfileImage} alt="" />
<div>
<input
ref={desc}
required
type="text"
placeholder="What's happening"
/>
<div className="postOptions">
<div
className="option"
style={{ color: "var(--photo)" }}
onClick={() => imageRef.current.click()}
>
<UilScenery />
Photo
</div>
<div className="option" style={{ color: "var(--video" }}>
<UilPlayCircle />
Video
</div>
<div className="option" style={{ color: "var(--location)" }}>
<UilLocationPoint />
Location
</div>
<div className="option" style={{ color: "var(--shedule)" }}>
<UilSchedule />
Schedule
</div>
<button
className="button ps-button"
onClick={handleSubmit}
disabled={loading}
>
{loading ? "Uploading..." : "Share"}
</button>
<div style={{ display: "none" }}>
<input
type="file"
name="myImage"
ref={imageRef}
onChange={onImageChange}
/>
</div>
</div>
{image && (
<div className="previewImage">
<UilTimes onClick={() => setImage(null)} />
<img src={URL.createObjectURL(image)} alt="" />
</div>
)}
</div>
</div>
</div>
);
};
export default PostShare;
I would be glad to provide any other details if that helps.
Update with other portions of code:
Dispatcher of RETRIEVING_SUCCESS:
import * as PostApi from '../api/PostRequest';
export const getTimelinePosts = (id) => async (dispatch) => {
dispatch({ type: 'RETRIEVING_START' });
try {
const { data } = await PostApi.getTimelinePosts(id);
dispatch({ type: 'RETRIEVING_SUCCESS', data: data });
} catch (error) {
dispatch({ type: 'RETRIEVING_FAIL' });
console.log(error);
}
};
getTimelinePosts usage:
import React, { useEffect } from 'react';
import './Posts.css';
import { PostsData } from '../../Data/PostsData';
import { useDispatch, useSelector } from 'react-redux';
import { getTimelinePosts } from '../../actions/postAction';
import Post from '../Post/Post';
const Posts = () => {
const dispatch = useDispatch();
const { user } = useSelector((state) => state.authReducer.authData);
let { posts, loading } = useSelector((state) => state.postReducer);
console.log('posts content', posts);
useEffect(() => {
dispatch(getTimelinePosts(user._id));
}, []);
return (
<div className="Posts">
{/* {posts.map((post, id) => {
return <Post data={post} id={id}></Post>;
})} */}
</div>
);
};
export default Posts;
in postReducer, let's remove the default on the switch statement, we don't need it on reducer because other actions will come here and the code make all states return the initial state.
I am getting the above error in my TypeScript code. I am attaching the codes of 2 files along with the error message. Please look into it.
This is the "NewPostForm.tsx" file in which error is occuring.
import React, { useState } from 'react';
import {AlertIcon, Flex, Icon, Alert, Text} from "#chakra-ui/react";
import {BiPoll} from "react-icons/bi";
import { BsLink45Deg, BsMic } from 'react-icons/bs';
import { IoDocumentText, IoImageOutline } from 'react-icons/io5';
import {AiFillCloseCircle, AiTwotoneWallet} from "react-icons/ai";
import TabItem from './TabItem';
import TextInputs from "./PostForm/TextInputs"
import { render } from 'react-dom';
import ImageUpload from './ImageUpload';
import { User } from 'firebase/auth';
import { useRouter } from 'next/router';
import { addDoc, collection, serverTimestamp, Timestamp, updateDoc } from 'firebase/firestore';
import { firestore, storage } from '../../firebase/clientApp';
import { getDownloadURL, ref, uploadString } from 'firebase/storage';
import { Post } from '../../atoms/postsAtom';
import useSelectFile from '../../hooks/useSelectFile';
type NewPostFormProps = {
user: User;
};
const formTabs = [
{
title: "Post",
icon: IoDocumentText,
},
{
title: "Images & Video",
icon: IoImageOutline,
},
{
title: "Link",
icon: BsLink45Deg,
},
{
title: "Poll",
icon: BiPoll,
},
{
title: "Talk",
icon: BsMic,
},
];
export type TabItem = {
title: string;
icon: typeof Icon.arguments;
};
const NewPostForm:React.FC<NewPostFormProps> = ({user}) => {
const router = useRouter();
const [selectedTab, setSelectedTab] = useState(formTabs[0].title);
const [textInputs, setTextInputs] = useState({
title: "",
body: "",
});
const {selectedFile, setSelectedFile, onSelectFile} = useSelectFile();
const [loading, setLoading] = useState(false);
const [error, setError] = useState(false);
const handleCreatePost = async() => {
const {communityId} = router.query;
// Create new post object => type Post
const newPost: Post = {
communityId: communityId as string,
creatorId: user?.uid,
creatorDisplayName: user.email!.split("#")[0],
title: textInputs.title,
body: textInputs.body,
numberOfComments: 0,
voteStatus: 0,
createdAt: serverTimestamp() as Timestamp,
id: ''
};
setLoading(true);
try {
// Store the post in DB
const postDocRef = await addDoc(collection(firestore, "posts"), newPost);
// Check for selected file
if(selectedFile)
{
// Store in storage => getDownloadURL {return imageURL}
const imageRef = ref(storage, `posts/${postDocRef.id}/image`);
await uploadString(imageRef, selectedFile, "data_url");
const downloadURL = await getDownloadURL(imageRef);
// Update post doc by adding imageURL
await updateDoc(postDocRef, {
imageURL: downloadURL,
});
}
// redirect the user back to the communityPage using the router
router.back();
}
catch(error: any)
{
console.log("handleCreatePost error", error.message);
setError(true);
}
setLoading(false);
};
const onTextChange = (
event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>
) => {
const {
target: {name, value},
} = event;
setTextInputs((prev) => ({
...prev,
[name]: value,
}));
};
return <div>
<Flex direction="column" bg="white" borderRadius={4} mt={2}>
<Flex width="100%">
{formTabs.map((item) => (
<TabItem key={item.title} item={item} selected={item.title === selectedTab}
setSelectedTab={setSelectedTab} />
))}
</Flex>
<Flex p={4}>
{selectedTab === "Post" && (
<TextInputs textInputs={textInputs} handleCreatePost={handleCreatePost}
onChange={onTextChange} loading={loading} />)}
{selectedTab === "Images & Video" && (
<ImageUpload
selectedFile={selectedFile}
onSelectImage={onSelectFile}
setSelectedTab={setSelectedTab}
setSelectedFile={setSelectedFile} />
)}
</Flex>
{error && (
<Alert status="error">
<AlertIcon />
<Text mr={2}>Error Creating the Post</Text>
</Alert>
)}
</Flex>
</div>
}
export default NewPostForm;
Also I am attaching another "useSelectFile.tsx" file for reference.
import React, {useState} from 'react';
const useSelectFile = () => {
const [selectedFile, setSelectedFile] = useState<string>();
const onSelectFile = (event: React.ChangeEvent<HTMLInputElement>) => {
console.log("THIS IS HAPPENING", event);
const reader = new FileReader();
if(event.target.files?.[0])
{
reader.readAsDataURL(event.target.files[0]);
}
reader.onload = (readerEvent) => {
if(readerEvent.target?.result)
{
setSelectedFile(readerEvent.target.result as string);
}
};
};
return
{
selectedFile
setSelectedFile
onSelectFile
};
};
export default useSelectFile;
Also I am attaching the screenshot of error message.
You have newline after return, so you are not returning anything from your useSelectFile hook. Remove the line break in return statement:)
You have return nothing from your hook file and the return object you are expecting is wrong
Try this
return {
selectedFile,
setSelectedFile,
onSelectFile,
};
a working sandbox is here
Currently, my project uses antd upload to upload an image before posting a post, and then registers a post.
Here, I am trying to implement a preview function when clicking on an image that has been uploaded.
However, if you click on an image for a specific file, the file is downloaded instead of a preview.
To solve this problem, I would like to specify the content-type in the header as well when sending the file.
I am wondering how to implement the function as I thought.
Here is the code for the upload component:
import React, { useCallback, useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { Button, Upload } from 'antd';
import { UploadOutlined } from '#ant-design/icons';
import PropTypes from 'prop-types';
import { IMAGES_PREVIEW, EDIT_POST_UPLOAD_IMAGES, UPLOAD_IMAGES_REQUEST, CHANGE_EDIT_POST_IMAGES } from '../../reducers/post';
import { ImageUploaderText, ImageUploaderWrapper } from '../../styles/postingForm';
const PostingUpload = ({ editPost }) => {
const dispatch = useDispatch();
const { editImagePaths, imagePaths, previewImagePaths } = useSelector((state) => state.post);
const onImagePreview = useCallback((e) => {
const uploadDone = editImagePaths.concat(imagePaths).filter((v) => v === e.name);
if (uploadDone.length > 0) {
window.open(`http://localhost:3065/${uploadDone}`, '_blank');
} else {
dispatch({
type: IMAGES_PREVIEW,
data: e.name,
});
};
}, []);
const normFile = useCallback((e) => {
if (Array.isArray(e)) {
return e;
}
return e?.fileList;
}, []);
const onChangeImages = useCallback((e) => {
const editImageFileList = e.fileList.filter((v) => v.status === 'done');
const imageFileList = e.fileList.filter((v) => v.percent === 0);
const editImages = editImageFileList.map((v) => v.name);
dispatch({
type: CHANGE_EDIT_POST_IMAGES,
data: editImages,
});
const imageFormData = new FormData();
imageFileList.forEach((f) => {
imageFormData.append('image', f.originFileObj);
});
dispatch({
type: UPLOAD_IMAGES_REQUEST,
data: imageFormData,
});
}, []);
const onBeforeUpload = useCallback((file, fileList) => {
return false
}, []);
const editPostImages = editPost?.Images.map((v, i) => {
return {
uid: v.uid,
name: v.src,
status: 'done',
thumbUrl: `http://localhost:3065/${v.src}`,
}
});
useEffect(() => {
if (editPost) {
const images = editPost.Images.map((v) => v.src);
dispatch({
type: EDIT_POST_UPLOAD_IMAGES,
data: images,
});
}
}, []);
useEffect(() => {
if (previewImagePaths) {
window.open(`http://localhost:3065/${previewImagePaths}`, '_blank');
}
}, [previewImagePaths]);
return (
<ImageUploaderWrapper
name="images"
rules={[
{
required: true,
},
]}
valuePropName="fileList"
getValueFromEvent={normFile}
initialValue={editPost && [...editPostImages]}
>
<Upload.Dragger
name="image"
listType="picture"
onChange={onChangeImages}
beforeUpload={onBeforeUpload}
onPreview={onImagePreview}
>
<ImageUploaderText className='bold'>
{editPost ? 'Drag edit files here or' : 'Drag files here OR'}
</ImageUploaderText>
<Button type='primary' size='large' icon={<UploadOutlined />}>Upload</Button>
</Upload.Dragger>
</ImageUploaderWrapper>
)
};
export default PostingUpload;
I am using a dialog box in a table to edit a row with axios.patch request. While clicking the edit button the values of that particular row are rendered into the TextFields which are in Dialog box but I'm unable to update the values. can anyone help me with this? Please see the Sandox link for better understanding. Thank you.
Sandbox link: https://codesandbox.io/s/material-demo-forked-gdxl3?file=/demo.js
code:
import React, { useState } from "react";
import {
Button,
Typography,
Dialog,
DialogActions,
DialogContent,
DialogTitle,
Table,
TableCell,
TableBody,
TableRow
} from "#material-ui/core";
import { axios } from "./Axios";
import { ValidatorForm, TextValidator } from "react-material-ui-form-validator";
import UserForm from "./UserForm";
import UserTable from "./Table";
export default function SimpleCard() {
const [users, setUsers] = useState([]);
const [postUser, setPostUser] = useState({
id: "",
name: "",
email: ""
});
// console.log(users)
const getUsers = async () => {
const response = await axios.get("/contacts");
if (response && response.data) {
setUsers(response.data);
}
};
React.useEffect(() => {
getUsers();
}, []);
// dialog
const [open, setOpen] = React.useState(false);
const [fullWidth, setFullWidth] = React.useState(true);
const [maxWidth, setMaxWidth] = React.useState("sm");
const handleClickOpen = () => {
setOpen(true);
};
const [open1, setOpen1] = React.useState(false);
const closeDialogForm = () => {
let userDetails = { ...postUser };
userDetails.id = "";
userDetails.name = "";
userDetails.email = "";
setPostUser(userDetails);
};
const handleClose = () => {
closeDialogForm();
setOpen(false);
};
const handleClose1 = () => {
closeDialogForm();
setOpen1(false);
};
const submitForm = async () => {
const response = await axios.post("/contacts", postUser).catch((error) => {
console.log(error);
});
console.log(response);
if (response) {
getUsers();
}
closeDialogForm();
};
const openEditUserDialog = (id) => {
let userDetails = { ...postUser };
for (let index = 0; index < users.length; index++) {
if (id === users[index].id) {
userDetails.id = users[index].id;
userDetails.name = users[index].name;
userDetails.email = users[index].email;
}
}
console.log(userDetails);
setPostUser(userDetails);
setOpen1(true);
};
const updateUser = async (id) => {
const response = await axios
.put(`/contacts/${id}`, postUser)
.catch((error) => {
console.log(error);
});
// console.log(response)
if (response) {
// setOpen(false);
getUsers();
}
};
const deleteUser = async (id) => {
const response = await axios.delete(`/contacts/${id}`).catch((err) => {
console.log(err);
});
if (response) {
getUsers();
}
};
return (
<div>
<Typography>Users</Typography>
<Button
size="small"
variant="contained"
onClick={handleClickOpen}
style={{ textTransform: "none" }}
>
Add
</Button>
<UserTable
users={users}
openEditUserDialog={openEditUserDialog}
deleteUser={deleteUser}
/>
{/* dialog */}
<Dialog
fullWidth={fullWidth}
maxWidth={maxWidth}
open={open}
// onClose={handleClose}
aria-labelledby="max-width-dialog-title"
>
<DialogTitle id="max-width-dialog-title">Add contact</DialogTitle>
<UserForm
submitForm={submitForm}
handleClose={handleClose}
postUser={postUser}
setPostUser={setPostUser}
/>
</Dialog>
{/* edit dialog */}
<Dialog
fullWidth={fullWidth}
maxWidth={maxWidth}
open={open1}
// onClose={handleClose}
aria-labelledby="edit-user"
>
<DialogTitle id="edit-user">Edit contact</DialogTitle>
<UserForm
submitForm={updateUser}
handleClose={handleClose1}
postUser={postUser}
setPostUser={setPostUser}
/>
</Dialog>
</div>
);
}
backend json data:
{
"contacts": [
{
"id": 1,
"name": "Gowtham",
"email": "gowtham#gmail.com"
},
{
"id": 2,
"name": "King",
"email": "gowthamKing#gmail.com"
},
{
"id": 3,
"name": "Hello",
"email": "gowthamKing123#gmail.com"
}
]
}
I have found the solution. Just replace the updateUser arrow function with below code
const updateUser = async () => {
let updateObject = {...postUser}
const response = await axios.patch(`/contacts/${updateObject.id}`, postUser).catch(error => { console.log(error) })
console.log(response)
if (response) {
// setOpen(false);
getUsers()
}
handleClose1();
}
I am trying to handle multiple inputs in a array of objects and each object I am mapping to the input field in a form .Now I am getting empty array I want to know where I am doing wrong .I am also sending post axios request and the value I am getting in input text fields through urlParmas using hooks.
import React, { useState, useEffect } from "react";
import ReactDOM from "react-dom";
import { useLocation } from "react-router-dom";
import axios from "axios";
import { Button, TextField } from "#material-ui/core";
const MyComponent = () => {
const [sale, setSale] = useState("");
const [district, setDistrict] = useState("");
const obj = [
{
key: 1,
label: "Sales office",
handleChange: (e) => {
setSale(e.target.value);
},
val: sale,
},
{
key: 2,
label: "Sales district",
handleChange: (e) => {
setDistrict(e.target.value);
},
val: sale,
},
];
const [object, setObject] = useState(obj);
const handleSubmit = () => {
axios
.post("localhots:8000", {
sale,
district,
})
.then(() => {});
setSale("");
setDistrict("");
};
const handleComment = (e, item) => {
e.preventDefault();
let result = object;
result = result.map((el) => {
if (el.name === item.name) el.name = e.target.value;
return el;
});
console.log(result);
setObject(result);
};
const { search } = useLocation();
const urlParams = Object.fromEntries([...new URLSearchParams(search)]);
useEffect(() => {
const { salesoff } = urlParams;
setSale(salesoff);
}, []);
object.map((item, index) => {
return (
<div>
<form
onSubmit={(e) => {
e.target.reset();
}}
>
<TextField
name={item.name}
value={item.sale}
label={item.label}
onChange={handleChange}
/>
<Button
type="submit"
fullWidth
variant="contained"
color="primary"
onClick={() => handleSubmit()}
>
Submit
</Button>
</form>
</div>
);
});
};
export default MyComponent;