I am currently to convert a video file to produce a thumbnail through ffmpeg, react-dropzone, and express. However I keep getting a error of "Cannot read properties of undefined (reading 'format')" in my console. For some reason it can not read the "metadata.format.duration" in my program, I have checked if ffmpeg is properly installed by running the ffmpeg --version in my console, and I get all the details, along with ffprobe --version as well.
Here is my code:
upload.js
router.post("/thumbnail", (req, res) => {
let thumbsFilePath ="";
let fileDuration ="";
// req.body.filepath
ffmpeg.ffprobe(req.body.filepath, function(err, metadata){
console.dir(metadata);
console.log(metadata.format.duration);
fileDuration = metadata.format.duration;
})
ffmpeg(req.body.filepath) //req.body.filepath
.on('filenames', function (filenames) {
console.log('Will generate ' + filenames.join(', '))
console.log(filenames);
thumbsFilePath = "./uploads/thumbnails/" + filenames[0];
})
.on('end', function () {
console.log('Screenshots taken');
return res.json({ success: true, thumbsFilePath: thumbsFilePath, fileDuration: fileDuration})
})
.screenshots({
// Will take screens at 20%, 40%, 60% and 80% of the video
count: 3,
folder: './uploads/thumbnails',
size:'320x240',
// %b input basename ( filename w/o extension )
filename:'thumbnail-%b.png'
});
})
FrontEnd drop code:
AddVideo.js
const onDrop = (files) => {
let formData = new FormData();
const config = {
header: { 'content-type': 'multipart/form-data' }
}
console.log(files)
formData.append("file", files[0])
axios.post('http://localhost:5000/api/upload/uploadfiles', formData, config)
.then(response => {
if (response.data.success) {
let variable = {
filePath: response.data.filePath,
fileName: response.data.fileName
}
setFilePath(response.data.filePath)
//gerenate thumbnail with this filepath !
axios.post('http://localhost:5000/api/upload/thumbnail', variable)
.then(response => {
if (response.data.success) {
setDuration(response.data.fileDuration)
setThumbnail(response.data.thumbsFilePath)
} else {
alert('Failed to make the thumbnails');
}
})
} else {
alert('failed to save the video in server')
}
})
}
return (
<div style={{ maxWidth: '700px', margin: '2rem auto' }}>
<div style={{ textAlign: 'center', marginBottom: '2rem' }}>
{/* <Title level={2} > Upload Video</Title> */}
</div>
<FormControl>
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
<Dropzone
onDrop={onDrop}
multiple={false}
maxSize={800000000}>
{({ getRootProps, getInputProps }) => (
<div style={{ width: '300px', height: '240px', border: '1px solid lightgray', display: 'flex', alignItems: 'center', justifyContent: 'center' }}
{...getRootProps()}
>
<input {...getInputProps()} />
<Icon type="plus" style={{ fontSize: '3rem' }} />
</div>
)}
</Dropzone>
</div>
</FormControl>
</div>
)
}
The video I am trying to upload is a mp4 file. I am using fluent-ffmpeg as a dependency.
Related
i have a simple app, that fetch my database via graphql node.js server, and i want to implement subscriptions to it, backend is already written, but i don`t know what to do in frontend.
so i have a query and subscription, and i`m returning a map of data with messages and displaying it in my application, what i need to update, to make it work with subscriptions?
export const SUBSCRIPTION_MESSAGES = gql`
subscription {
messageCreated {
content
id
user
}
}
`;
export const GET_MESSAGES = gql`
query {
messages {
content
id
user
}
}
`;
<Messages user={state.user} />
--------------------
import { useQuery, useSubscription } from "#apollo/client";
import { useEffect } from "react";
import { GET_MESSAGES, SUBSCRIPTION_MESSAGES } from "../graphql/queries";
const Messages = ({ user }: any) => {
const { subscribeToMore, data } = useQuery(GET_MESSAGES);
console.log(subscribeToMore);
useEffect(() => {
subscribeToMore({
document: SUBSCRIPTION_MESSAGES,
updateQuery: (prev, { subscriptionData }: any) => {
if (!subscriptionData.data) return prev;
const newMessage = subscriptionData.data.messageCreated;
return Object.assign({}, prev, {
messages: [newMessage, ...prev.messages],
});
},
});
}, []);
if (!data) {
console.log("lol");
return null;
}
return (
<div>
{data.messages.map(({ id, user: messageUser, content }: any) => (
<div
key={id}
style={{
display: "flex",
justifyContent: user == messageUser ? "flex-end" : "flex-start",
paddingBottom: "1em",
}}
>
{user != messageUser && (
<div
style={{
height: 50,
width: 50,
marginRight: "0.5em",
border: "2px solid #e5e6ea",
borderRadius: 25,
textAlign: "center",
fontSize: "18pt",
paddingTop: 5,
}}
>
{messageUser.slice(0, 2).toUpperCase()}
</div>
)}
<div
style={{
background: user == messageUser ? "#58bf56" : "#e5e6ea",
color: user == messageUser ? "white" : "black",
paddingBottom: "1em",
borderRadius: "1em",
maxWidth: "60%",
padding: "10px",
}}
>
{content}
</div>
</div>
))}
</div>
);
};
export default Messages;
I have created a survey form with formik in react hooks. Initial state values of react variables are fetched by the database. I have created an icon button that increments the value of votes by one onclick. The problem is whenever I have clicked on icon value not incremented by.
Initial state before clicking on icon
result after clicking on icon
I have attached the above screenshot of the output before and after a click on the button.
Code:
// #ts-ignore
import React, { useState, useEffect } from 'react';
import { Formik, Form, Field } from 'formik';
import {
Typography,
Button,
Grid,
CircularProgress,
Divider,
} from '#material-ui/core';
import * as Yup from 'yup';
import { MyInput } from './comman/MyInput';
import axios from 'axios';
import { Event } from '../Tracking/Event';
import ThumbUpAltIcon from '#material-ui/icons/ThumbUpAlt';
import Unsubscribed from './Unsubscribed';
const contactSchema = Yup.object().shape({});
export default function SurveyUnsubscribed(props: any) {
const [isSubmitted, setIsSubmitted] = useState(false);
const [loading, setLoading] = useState(false);
const [count, setCount] = useState(0);
const [countone, setCountOne] = useState(0);
const [counttwo, setCountTwo] = useState(0);
const [countthree, setCountThree] = useState(0);
const [state, setState] = useState({
msg: '',
});
async function getInitialValues() {
try {
const response = await axios.get(
`${process.env.REACT_APP_LOCALHOST_DEVELOPMENT_VOTING_API_GET}`,
);
var voteone = response.data.map(function (obj: any) {
console.log('value',parseInt(obj.voteone))
return parseInt(obj.voteone);
});
var votetwo = response.data.map(function (obj: any) {
return obj.votetwo;
});
var votethree = response.data.map(function (obj: any) {
return obj.votethree;
});
var votefour = response.data.map(function (obj: any) {
return obj.votefour;
});
return {
voteone,
votetwo,
votethree,
votefour,
helptext: '',
};
} catch (error) {
console.error(error);
}
}
useEffect(() => {
getInitialValues().then((res: any) => setCount(res.voteone));
getInitialValues().then((res: any) => setCountOne(res.votetwo));
getInitialValues().then((res: any) => setCountTwo(res.votethree));
getInitialValues().then((res: any) => setCountThree(res.votefour));
}, []);
return (
<React.Fragment>
<Formik
enableReinitialize
initialValues={{
count: count,
countone: countone,
counttwo: counttwo,
countthree: countthree,
helptext: '',
}}
validationSchema={contactSchema}
onSubmit={(values, { resetForm }) => {
setLoading(true);
const data = {
count: values.count,
countone: values.countone,
counttwo: values.counttwo,
countthree: values.countthree,
helptext: values.helptext,
};
const request = new Request(
`${process.env.REACT_APP_LOCALHOST_DEVELOPMENT_VOTING_API}`,
{
method: 'POST',
headers: new Headers({
'Content-Type': 'application/json',
}),
body: JSON.stringify(data),
},
);
fetch(request)
.then((res) => res.json())
.then((data) => {
if (data.message === 'Thank you for your feedback!') {
setState({
msg: data.message,
});
setIsSubmitted(true);
setTimeout(() => {
setLoading(false);
}, 1500);
} else {
console.log('error');
}
});
setTimeout(() => {
setIsSubmitted(false);
}, 1500);
resetForm();
}}
>
{({ setFieldValue }) => (
<Grid container>
<Grid
item
xs={12}
style={{ paddingLeft: '2em', paddingRight: '2em' }}
>
{isSubmitted}
<Form>
<Typography
variant="body1"
style={{
display: 'flex',
alignItems: 'center',
marginBottom: '1em',
}}
>
<Field
type="hidden"
name="count"
component={ThumbUpAltIcon}
onClick={() => setCount( count + 1 )}
style={{ color: '#C4C4C4', marginRight: '0.4em' }}
/>
<Typography
variant="caption"
style={{
position: 'relative',
top: '1.5em',
right: '1.5em',
}}
>
{count}
</Typography>
Complaince and Tax Return Filing Dates.
</Typography>
<Typography
variant="body1"
style={{
display: 'flex',
alignItems: 'center',
marginBottom: '1em',
}}
>
<Field
type="hidden"
name="countone"
component={ThumbUpAltIcon}
onClick={() => setCountOne( countone + 1 )}
style={{ color: '#C4C4C4', marginRight: '0.4em' }}
/>
<Typography
variant="caption"
style={{
position: 'relative',
top: '1.5em',
right: '1.5em',
}}
>
{countone}
</Typography>
Excel Sheet for Calculation of GSTR 3B.
</Typography>
<Typography
variant="body1"
style={{
display: 'flex',
alignItems: 'center',
marginBottom: '1em',
}}
>
<Field
type="hidden"
name="counttwo"
component={ThumbUpAltIcon}
onClick={() => setCountTwo( counttwo + 1 )}
style={{ color: '#C4C4C4', marginRight: '0.4em' }}
/>
<Typography
variant="caption"
style={{
position: 'relative',
top: '1.5em',
right: '1.5em',
}}
>
{counttwo}
</Typography>
Excel Sheet for GSTR 2A vs ITC Books matching.
</Typography>
<Typography
variant="body1"
style={{
display: 'flex',
alignItems: 'center',
marginBottom: '1em',
}}
>
<Field
type="hidden"
name="countthree"
component={ThumbUpAltIcon}
onClick={() => setCountThree(countthree + 1)}
style={{ color: '#C4C4C4', marginRight: '0.4em' }}
/>
<Typography
variant="caption"
style={{
position: 'relative',
top: '1.5em',
right: '1.5em',
}}
>
{countthree}
</Typography>
Details of applicable law on directors and requirement of
Director KYC.
</Typography>
<br />
<Typography
variant="h6"
style={{
marginLeft: '2em',
marginTop: '0.5em',
}}
>
What information would help you ?
</Typography>
<Field
id="outlined-multiline-flexible"
type="text"
name="helptext"
component={MyInput}
disabled={isSubmitted}
style={{ marginLeft: '2em' }}
/>
<br />
<br />
<Button
type="submit"
variant="contained"
style={{
background: '#2F4858',
color: 'white',
fontFamily: 'roboto',
fontSize: '1rem',
marginLeft: '2em',
marginBottom: '1em',
}}
>
{loading && (
<CircularProgress
size={25}
color="inherit"
style={{ marginRight: '5px' }}
/>
)}
{loading && <span>submitting</span>}
{!loading && <span>Submit</span>}
</Button>
<br />
{state.msg && (
<Typography
variant="h6"
style={{
color: '#4BB543',
fontFamily: 'roboto-medium',
marginTop: '1em',
}}
>
{' '}
{state.msg}{' '}
</Typography>
)}
</Form>
<Divider
style={{
border: '1px solid #97A1A8',
marginTop: '1em',
marginBottom: '2em',
}}
/>
</Grid>
</Grid>
)}
</Formik>
</React.Fragment>
);
}
Whenever I have clicked on the thumbs-up icon value is incremented by one but value 1 is inserted in front of the previous one. I want to increment value by one. ( 1 increment by 2 ).
Thanks In advance guys.
It's the nature of javascript when you add a string to a number
console.log(1+"1") // <-- Gives "11"
console.log(1+1) // <-- Gives "2"
Your first count is fine, but when you get a response from the API, your res.voteone is definitely a string.
So you will need to parse your response to a number first:
useEffect(() => {
getInitialValues().then((res: any) => setCount(Number(res.voteone)));
getInitialValues().then((res: any) => setCountOne(Number(res.votetwo)));
getInitialValues().then((res: any) => setCountTwo(Number(res.votethree)));
getInitialValues().then((res: any) => setCountThree(Number(es.votefour)));
}, []);
OR
useEffect(() => {
getInitialValues().then((res: any) => setCount(parseInt(res.voteone)));
getInitialValues().then((res: any) => setCountOne(parseInt(res.votetwo)));
getInitialValues().then((res: any) => setCountTwo(parseInt(res.votethree)));
getInitialValues().then((res: any) => setCountThree(parseInt(es.votefour)));
}, []);
Number() and parseInt() behaves a bit different but in your case it's not.
This is the result of type coercion. As in, in javasript "1"+1 gives 11. To fix, you should convert the results from response to number.
useEffect(() => {
getInitialValues().then((res: any) => setCount(Number(res.voteone)));
getInitialValues().then((res: any) => setCountOne(Number(res.votetwo)));
getInitialValues().then((res: any) => setCountTwo(Number(res.votethree)));
getInitialValues().then((res: any) => setCountThree(Number(res.votefour)));
}, []);
I am working on a Mern-stack Application, but I'm not able to clear the input field after a successful post Request. I am using a function-based component with useEffect.
I tried examples I got here on Stack Overflow but it still didn't work. After submitting successfully the input still left in the input field. How do I make this to clear?
I have tried setCommentData([]) after the submit but it didn't work.
Here is my Component
export default function EventAndComments(props) {
const EventComment = (props) => (
<CardContent>
<Typography variant="body2" color="textSecondary" component="p">
{props.comment.name}
</Typography>
<Typography variant="body2" color="textSecondary" component="p">
{props.comment.description}
</Typography>
</CardContent>
);
const theme = useTheme();
const [events, setEventData] = useState([]);
const [comments, setCommentData] = useState([]);
const useStyles = makeStyles((theme) => ({
root: {
maxWidth: 550,
},
media: {
height: 0,
paddingTop: "86%", // 16:9
display: "flex",
flexDirection: "column",
alignItems: "center",
},
expand: {
transform: "rotate(0deg)",
marginLeft: "auto",
transition: theme.transitions.create("transform", {
duration: theme.transitions.duration.shortest,
}),
},
expandOpen: {
transform: "rotate(180deg)",
},
avatar: {
backgroundColor: red[500],
},
}));
const classes = useStyles();
const [expanded, setExpanded] = React.useState(false);
const handleExpandClick = () => {
setExpanded(!expanded);
};
useEffect(() => {
axios
.get(
"http://localhost:9000/events/" +
props.match.params.id +
"/eventcomments"
)
.then((response) => {
setEventData(response.data);
})
.catch(function (error) {
console.log(error);
});
}, []);
const onPageLoad = () => {
axios
.get(
"http://localhost:9000/events/" +
props.match.params.id +
"/eventcomments"
)
.then((response) => {
setCommentData(response.data.eventcomments);
})
.catch(function (error) {
console.log(error);
});
};
useEffect(() => {
onPageLoad();
}, []);
const nowIso = new Date();
const getTitle = (startDateTs, endDateTs) => {
const now = Date.parse(nowIso);
if (endDateTs <= now) {
return "Started:" + " " + moment(startDateTs).format("LLLL");
}
if (startDateTs < now && endDateTs > now) {
return "Live:" + " " + moment(startDateTs).format("LLLL");
}
return "Starting:" + " " + moment(startDateTs).format("LLLL");
};
const getEnded = (startDateTs, endDateTs) => {
const now = Date.parse(nowIso);
if (endDateTs <= now) {
return "Ended:" + " " + moment(startDateTs).format("LLLL");
}
if (startDateTs < now && endDateTs > now) {
return "Will End:" + " " + moment(startDateTs).format("LLLL");
}
return "Ends:" + " " + moment(startDateTs).format("LLLL");
};
const [eventDescription, setEventComment] = React.useState("");
const [name, setName] = React.useState("");
const handleChange = (parameter) => (event) => {
if (parameter === "name") {
setName(event.target.value);
}
if (parameter === "description") {
setEventComment(event.target.value);
}
};
const onSubmit = useCallback(
(e) => {
e.preventDefault();
axios
.post(
"http://localhost:9000/events/" +
props.match.params.id +
"/eventcomment",
{ name: name, description: eventDescription }
)
.then(function (response) {
onPageLoad();
})
.catch(function (error) {
console.log(error);
});
},
[props.match.params.id, name, eventDescription]
);
let eventCommentList = comments.map((comment, k) => (
<EventComment comment={comment} key={k} />
));
return (
<Grid
container
spacing={0}
direction="column"
alignItems="center"
justify="center"
style={{ minHeight: "100vh" }}
>
<Card className={classes.root}>
<h3
style={{
background: " #800000",
color: "white",
textAlign: "center",
}}
className={classes.cardheader}
>
{events.title}
</h3>
<CardHeader
avatar={
<Avatar aria-label="recipe" className={classes.avatar}>
CB
</Avatar>
}
action={
<IconButton aria-label="settings">
<MoreVertIcon />
</IconButton>
}
title={getTitle(
Date.parse(events.startingDate),
Date.parse(events.closingDate)
)}
subheader={getEnded(
Date.parse(events.startingDate),
Date.parse(events.closingDate)
)}
style={{ background: "#DCDCDC" }}
/>
<CardMedia
className={classes.media}
image={events.eventImage}
title="Paella dish"
/>
<CardContent>
<Typography variant="body2" color="textSecondary" component="p">
{events.description}
</Typography>
</CardContent>
</Card>
<form
className={classes.root}
noValidate
autoComplete="off"
onSubmit={onSubmit}
>
<FormControl>
<InputLabel htmlFor="component-simple">Name</InputLabel>
<Input
id="component-simple"
value={name}
onChange={handleChange("name")}
label="Name"
/>
</FormControl>
<FormControl variant="outlined">
<InputLabel htmlFor="component-outlined">Description</InputLabel>
<OutlinedInput
id="component-outlined"
value={eventDescription}
onChange={handleChange("description")}
label="Description"
/>
</FormControl>
<Button type="submit" fullWidth variant="contained" color="primary">
Create Comment
</Button>
</form>
<CardContent>{eventCommentList}</CardContent>
</Grid>
);
}
}
I have added all my codes above.
In your onSubmit function, call setName("") and setEventComment("") to clear those values.
Also, just to follow conventions, I would rename setEventComment to setEventDescription since the state variable is named eventDescription not eventComment.
They have passed me a project of a web shop made with node.js and reactj and when I execute it loads the web but then it leaves an error message, it is because in some section there is no data or there is no code, but I do not want to insert it, my Professor told me to put a conditional so that when I do not find code I also upload the web but I do not know where to put the code or where to act, i am new on stackoverflow, thanks a lot
60 | let campaigns: any = [];
61 |
62 | if (this.props.categories && this.props.categories.isFinished) {
> 63 | if (this.props.categories.queryResult.data) {
| ^
64 | categories = this.props.categories.queryResult.data;
65 | } else if (this.props.categories.queryResult.length) {
66 | categories = this.props.categories.queryResult;
import * as React from "react";
import { Component } from "react";
import "./MenuBar.css";
import Menu from "./Menu";
import { List } from "semantic-ui-react";
import icon1 from "../../assets/icons/bars1.png";
import icon2 from "../../assets/icons/bars2.png";
import icon3 from "../../assets/icons/bars3.png";
import icon1r from "../../assets/icons/bars1_w.png";
import icon2r from "../../assets/icons/bars2_w.png";
import icon3r from "../../assets/icons/bars3_w.png";
import { services } from "../../store";
import { connect } from "react-redux";
import Radium from "radium";
import MenuFilters from "./MenuFilters";
export interface Props {
// Actions
fetchCategories: any;
fetchShops: any;
fetchCampaigns: any;
// Props
name: string;
avatar: string;
userId: string;
classes: any;
categories: any;
shops: any;
campaigns: any;
// Events
onChangeGrid: any;
}
interface State {
isOpen: boolean;
grid: string;
}
class _MenuBar extends Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = {
isOpen: true,
grid: "grid1"
};
}
public componentDidMount() {
this.props.fetchCategories();
this.props.fetchShops();
this.props.fetchCampaigns();
}
public render() {
let categories: any = [];
let shops: any = [];
let campaigns: any = [];
if (this.props.categories && this.props.categories.isFinished) {
if (this.props.categories.queryResult.data) {
categories = this.props.categories.queryResult.data;
} else if (this.props.categories.queryResult.length) {
categories = this.props.categories.queryResult;
}
}
if (this.props.shops && this.props.shops.isFinished) {
if (this.props.shops.queryResult.data) {
shops = this.props.shops.queryResult.data;
} else if (this.props.shops.queryResult.length) {
shops = this.props.shops.queryResult;
}
}
if (this.props.campaigns && this.props.campaigns.isFinished) {
if (this.props.campaigns.queryResult.data) {
campaigns = this.props.campaigns.queryResult.data;
} else if (this.props.campaigns.queryResult.length) {
campaigns = this.props.campaigns.queryResult;
}
}
return (
<div className="MCMenuBar">
<div className="MCMenuBarContainer">
<div
style={{
display: "inline-flex",
width: "50%"
}}
>
<Menu categories={categories} shops={shops} campaigns={campaigns} />
<div className="MCMenuBarDivider" />
<div
style={{
height: "50px",
marginTop: "10px"
}}
>
<List horizontal>
<List.Item as="a">
<span style={{ color: "#000", fontWeight: "bold" }}>
NUEVOS
</span>
</List.Item>
<List.Item as="a">
<span style={{ color: "#000", fontWeight: "bold" }}>
GRATIS
</span>
</List.Item>
<List.Item as="a">
<span style={{ color: "#000", fontWeight: "bold" }}>
PROMOS
</span>
</List.Item>
<List.Item as="a">
<span style={{ color: "#000", fontWeight: "bold" }}>
JUEGOS
</span>
</List.Item>
</List>
</div>
</div>
<div
style={{
height: "38px",
width: "50%",
textAlign: "right"
}}
>
<List horizontal>
<List.Item
as="a"
onClick={() => {
if (this.props.onChangeGrid) {
this.setState({ grid: "grid1" });
this.props.onChangeGrid("grid1");
}
}}
>
<span style={{ color: "#000", fontWeight: "bold" }}>
<img
src={this.state.grid === "grid1" ? icon1 : icon1r}
alt="Mi chollo"
style={style.baricon}
/>
</span>
</List.Item>
<List.Item
as="a"
onClick={() => {
if (this.props.onChangeGrid) {
this.setState({ grid: "grid2" });
this.props.onChangeGrid("grid2");
}
}}
>
<span style={{ color: "#000", fontWeight: "bold" }}>
<img
src={this.state.grid === "grid2" ? icon2 : icon2r}
alt="Mi chollo"
style={style.baricon}
/>
</span>
</List.Item>
<List.Item
as="a"
onClick={() => {
if (this.props.onChangeGrid) {
this.setState({ grid: "grid3" });
this.props.onChangeGrid("grid3");
}
}}
>
<span style={{ color: "#000", fontWeight: "bold" }}>
<img
src={this.state.grid === "grid3" ? icon3 : icon3r}
alt="Mi chollo"
style={style.baricon}
/>
</span>
</List.Item>
<List.Item>
<div />
</List.Item>
</List>
<div
style={{
display: "inline-flex",
borderLeft: "1px solid #ededed",
paddingLeft: "10px",
height: "58px",
marginTop: "-12px",
position: "relative",
top: "2px"
}}
>
<div
style={{
display: "inline-flex",
paddingTop: "10px"
}}
>
<MenuFilters />
</div>
</div>
</div>
</div>
</div>
);
}
}
const style = {
baricon: {
width: "24px",
height: "24px",
opacity: 0.4
}
};
const mapDispatchToProps = (dispatch: any) => {
return {
// same effect
fetchCategories: () => {
dispatch(services["api/v1/categories"].find());
},
fetchShops: () => {
dispatch(services["api/v1/shops"].find());
},
fetchCampaigns: () => {
dispatch(services["api/v1/campaigns"].find());
}
};
};
const mapStateToProps = (store: any) => {
return {
categories: store.categories,
shops: store.shops,
campaigns: store.campaigns
};
};
const MenuBar = connect(
mapStateToProps,
mapDispatchToProps
)(_MenuBar);
export default Radium(MenuBar);
As the error explains your queryResult property is null. Add another conditional check to see if the queryResult field is not empty in the line above (62)
if (
this.props.categories &&
this.props.categories.isFinished &&
!!this.props.categores.queryResult
) {
// user queryResult
}
Another option would be to set a default value for queryResult and update all it's references.
const qResult = this.props.categories.queryResult || [];
if (response && response.data && response.data.length > 0) {
}
I need to convert this from a functional component to a class component so I can take advantage of the componentDidMount method of React.Component.
const receivedStyle = {
marginRight: '0',
marginLeft: 'auto',
};
const receivedBubble = {
backgroundColor: '#709AFF',
color: 'white',
};
const receivedDate = {
marginRight: '0',
marginLeft: 'auto',
};
const MessageBubble = ({ message, received }) => (
<div className="message-bubble" style={received ? receivedStyle : null}>
<div className="bubble" style={received ? receivedBubble: null}>
{message.message}
</div>
<span className="date" style={received ? receivedDate: null}>{Moment(message.timestamp).startOf('minute').fromNow()}</span>
</div>
);
export default MessageBubble;
I don't understand what's the problem. Anyway, here it goes:
import React, { Component } from 'react'
const receivedStyle = {
marginRight: '0',
marginLeft: 'auto',
}
const receivedBubble = {
backgroundColor: '#709AFF',
color: 'white',
}
const receivedDate = {
marginRight: '0',
marginLeft: 'auto',
}
export default class MessageBubble extends Component {
componentDidMount() {
...
}
render() {
const { message, received } = this.props
return (
<div className="message-bubble" style={received ? receivedStyle : null}>
<div className="bubble" style={received ? receivedBubble: null}>
{message.message}
</div>
<span
className="date"
style={received ? receivedDate: null}
>
{Moment(message.timestamp).startOf('minute').fromNow()}
</span>
</div>
)
}
}