Pass control prop to child component in react hook form - javascript

I'm trying to pass the control prop to my custom component that comes from react-hook-form but it tells that the control is undefined
I did the same thing written in document. I used FormProvider like this:
<FormProvider {...methods}>
<form
style={{
height: "auto",
width: "90%",
padding: "2em",
paddingTop: "0",
textAlign: "center",
backgroundColor: "white",
borderRadius: "10px",
}}
onSubmit={methods.handleSubmit((data) => console.log(data))}
>
<IconButton
color="error"
onClick={() => setRecordControl({ stat: "" })}
>
<Cancel fontSize="large" />
</IconButton>
<h3 style={{ marginBottom: "10px", textAlign: "center" }}>
saving records
</h3>
{filtered.ListColumnInfo.map(
(detail) =>
detail.VisibleColumn && (
<div key={uuidV4()}>
<CustomTextBoxComponent
filtered={detail}
/>
</div>
)
)}
<Button
variant="contained"
fullWidth
color="success"
sx={{ mt: "1em" }}
type="submit"
>
save
</Button>
</form>
</FormProvider>
and I tried to retrieve the control inside of my CustomTextBoxComponent like this:
const CustomTextBoxComponent = ({ filtered }) => {
const { control } = useFormContext();
return (
<Controller
name="input"
render={({ field }) => (
<TextField
fullWidth
placeholder={
filtered.ElsRecord.PersianName !== ""
? filtered.ElsRecord.PersianName
: filtered.ElsRecord.Name
}
sx={{ marginBlock: "1em" }}
{...control}
{...field}
/>
)}
defaultValue=""
/>
);
};
it didn't work. always says the method is null
the picture of Error
how can I solve it?

Related

How to map transition in mui?

I want to map my products in mui and put each one in Grow, but with this error Warning: Failed prop type: Invalid prop children of type array supplied to ForwardRef(Grow), expect a single ReactElement . I will be
what should i do
if (enter) {
return (
<Box
sx={{
display: "grid",
gridTemplateColumns: "repeat(auto-fit, 250px)",
gap: "10px",
alignItems: "center",
justifyContent: "space-evenly",
padding: "0 50px",
height: "100%",
}}
>
{searchState.length ? (
<>
<Grow in={true}>
{searchState.map((item) => (
<Product key={item.id} productData={item} />
))}
</Grow>
<Grow
in={true}
style={{ transformOrigin: "0 0 0" }}
{...(true ? { timeout: 1000 } : {})}
>
{searchState.map((item) => (
<Product key={item.id} productData={item} />
))}
</Grow>
</>
) : (
<Box sx={{stylesNone}>No products found</Box>
)}
</Box>
);
}
You can wrap your mapped components with a div or fragment (<></>)
<Grow in={true}>
<>
{searchState.map((item) => (
<Product key={item.id} productData={item} />
))}
</>
</Grow>

Importing and using vanila JS functions in React component

I am very new to react.js and JavaScript, so apologies in advance. I'm trying to integrate https://diagrams.net into other webpage using the file that's directly given by diagrams.net here:
https://github.com/jgraph/drawio-integration/blob/master/diagram-editor.js?fbclid=IwAR1FMViVLW3Tba8RqMOUJtv16vIvPPycLYyu4rEtRTbuhbyztlrLXu5UyHo.
So as it can be seen in this example here: http://jgraph.github.io/drawio-integration/javascript.html, when the user double clicks on the diagram, they should be redirected to diagrams.net web and draw their own diagram.
The problem is that my web is currently built on React, and all the diagrams.net is built on vanilla JS. By inspecting the example above, they apparently use:
<img
style="cursor:pointer;"
title="Click to edit image"
onclick="DiagramEditor.editElement(this);"
src="data:image/png;base64,iVBORw0...
in the HTML to display the image of the diagram. I've tried to change it to react-like by changing it to:
<img alt="Click to edit image"
onClick={EditDiagram.DiagramEditor.editElement(this)}
src="data:image/png;base64,iVBORw0..."/>
and importing the JavaScript file by import * as EditDiagram from "../components/workarea/workarea-diagram-editor";, but it is returning TypeError: Cannot read properties of undefined (reading 'editElement').
I've also tried using dangerouslySetInnerHTML like this:
<div
dangerouslySetInnerHTML={{
__html:
"<img style='cursor:pointer;'
title='Click to edit image' onclick='DiagramEditor.editElement(this);'
src='data:image/png;base64,iVBORw0...'/>",
}}/>
but this way, that DiagramEditor.editElement(this) cannot be accessed that way.
I've been trying to get this to work for past 12 hours, but just can't get it to work. Is there any way to make this work?
Thank you so much.
Below is the React code that the JavaScript is being added on.
const WorkArea = () => {
const router = useRouter();
const formik = useFormik({
initialValues: {
scenario: "This is scenario",
},
validationSchema: Yup.object({
scenario: Yup.string().max(255).required("Scenario is required"),
}),
onSubmit: () => {
router.push("/");
},
});
const [countList, setCountList] = useState([0]);
// const [inputList, setInputList] = useState([]);
const AddScenario = () => {
let countArr = [...countList];
let counter = countArr.slice(-1)[0];
counter++;
countArr.push(counter);
setCountList(countArr);
};
const DeleteScenario = () => {
let countArr = [...countList];
let counter = countArr.slice(-1)[0];
counter--;
countArr.pop(counter);
setCountList(countArr);
};
// const onAddBtnClick = (event) => {
// setInputList(inputList.concat(<SetScenario key={inputList.length} />));
// };
return (
<>
<Head>
<title>Work Area | Cybersecurity Requirements Generator</title>
</Head>
<Box
component="main"
sx={{
alignItems: "center",
display: "flex",
flexGrow: 1,
minHeight: "100%",
}}
>
<Container maxWidth="xl">
<NextLink href="/projects" passHref>
<Button component="a" startIcon={<ArrowBackIcon fontSize="small" />}>
Back to Projects
</Button>
</NextLink>
<form onSubmit={formik.handleSubmit}>
<Box sx={{ my: 3 }}>
<Typography color="textPrimary" variant="h4">
Use Case Diagram
</Typography>
<Typography color="textSecondary" gutterBottom variant="body2">
Make your own diagram!
</Typography>
</Box>
<Box
sx={{
py: 2,
}}
>
{/* <div
dangerouslySetInnerHTML={{
__html:
"<img style='cursor:pointer;' title='Click to edit image' onclick='DiagramEditor.editElement(this);' src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHkAAAA9CAYAAACJM8YzAAADT3RFWHRteGZpbGUAJTNDbXhmaWxlJTIwaG9zdCUzRCUyMmVtYmVkLmRpYWdyYW1zLm5ldCUyMiUyMG1vZGlmaWVkJTNEJTIyMjAyMS0wMS0xMVQxMCUzQTQxJTNBMzQuMjQ4WiUyMiUyMGFnZW50JTNEJTIyNS4wJTIwKE1hY2ludG9zaCUzQiUyMEludGVsJTIwTWFjJTIwT1MlMjBYJTIwMTFfMV8wKSUyMEFwcGxlV2ViS2l0JTJGNTM3LjM2JTIwKEtIVE1MJTJDJTIwbGlrZSUyMEdlY2tvKSUyMENocm9tZSUyRjg3LjAuNDI4MC44OCUyMFNhZmFyaSUyRjUzNy4zNiUyMiUyMGV0YWclM0QlMjJtNXI1QVhFdDE3eWx2WWlEWXo5UyUyMiUyMHZlcnNpb24lM0QlMjIxNC4xLjklMjIlMjB0eXBlJTNEJTIyZW1iZWQlMjIlM0UlM0NkaWFncmFtJTIwaWQlM0QlMjJlbVlSU0REUmtEUDJZZDNFWnkzciUyMiUyMG5hbWUlM0QlMjJQYWdlLTElMjIlM0VqWkxOVG9Rd0VJQ2ZwbGV6MEloNkZkZjE0Z2tUejVXT3ROblNrbElXOE9sdDdWUm9OaVplWU9hYjZmd1RXdmZMeWJKQnZCb09pcFFIdmhENlJNcXlxS283JTJGd3RramVTV1BrVFFXY2tqT215Z2tWJTJCQUx4T2RKSWNSV1VUT0dPWGtrTVBXYUEydHl4aXoxc3k1MjZkUmVkYUJkWkI1Qk5DMFRGM1RkOG1kaVBTJTJCckRiJTJCQXJJVEtYTlJZWDhmckQxMzFrd2E4Mm1qSVZwNmxzSmdEYU5nM013N1JJJTJCRTF0WVlGNlYlMkJxVUdGc2VZVGUlMkY3RGlpV1BiazFOcEZvdGFQZXZDS21KQzFNVHhuZ1RjZ3d1NGNQQ0ZtQjBOMWVaWmlFZE5BTnJnejc3a3lEMFViaGVlYTN3NG5VaFdPd0ZySU5saDdDd0U1Z2VuRjI5QzFyVDBOWmNuYmZsRkltSjNXSXFaQXp2b2ZzTnZNM0JDemlLcEc0NyUyQkxIdGJwd2V2d0UlM0QlM0MlMkZkaWFncmFtJTNFJTNDJTJGbXhmaWxlJTNFoE8CRAAABV1JREFUeF7tm1lIlVsYht+NXoSipGkIGpoDBYqiKIIQSCiRSigOCV2odZuSw51KoYaR8xCkGDmiaCDiVM5JSQiKoSiFaVk5UoKK4nz4Fmd73KmdvZX28ez1rZst7rXW/7/vs961vl/8FQB2wU2nHVAQ5J2dHZ0WKbM4PT29XQF5d5fDrIsLgbgyZF0ku08TQ9ZxwCSPITNkCRyQQCInmSFL4IAEEjnJDFkCBySQyElmyBI4IIFETjJDlsABCSRykhmyBA5IIJGTzJAlcEACiZxkhiyBAxJI5CQzZAkckEAiJ5khS+CABBJPTZLpRra3t6Gvry+B7dqVqDXI379/h5WV1ZHq2tvbERUVha9fvx7o8+DBA3z+/BmlpaVquaNpf7UmBfDlyxf09/cjNDRU3SEq/U46/lgX1eZ/a1JK5+bmxH2+f/8efn5+4tPMzEz8bnR09EjIk5OTWF9fx+XLl9XSqWl/tSYF0NjYiHv37uHTp0/qDlHpd9Lxx7qoNiHvv8GBgQG4u7tjfn4e5ubm4quOjg7cunULd+7cQUVFBc6fP4+ioiLR79mzZ5idnUViYiLq6+uRn58PmiMwMBCFhYUwNjZW0a9pfxqcnp6OyspKbG1twd/fHxkZGfTWwd68tHB8fHwwMTGB4OBgvHjxQqQ6ISEBHz58wLVr15CTk4Nz585hcXERtJvU1NSIRfzo0SM4OTkdGH9caJqO09p2rQ5kX19fBAUF4fbt28Iwejeru7sb9+/fB5mcnZ0tFkVtbS1MTEwQHx+PiIgIxMXFqejWtP/w8LAAUFxcLOal7fjp06fiXpRtdXUVeXl5yM3NRWtrKywtLWFhYYHo6GiEhITg8ePHWFpaQm9vLzIzM8WiffjwIV6+fImkpCT8/PlTzKkc7+bmpimrY/c/dZBXVlZgaGgojLx586YwTgktLS0N1tbWKCgoQGRkpDBubW0Nly5dOhSyuv3HxsZE+jw9PfHt2zcBmdJM193f9m+3BCsrKwtTU1NQKBQizXSczMzMIDU1Fe/evUNZWRkcHR3x9u1bENTOzs4TbffHpXyqINN2rTy337x5gytXrohXPJSQy8vLhbG0RVIjEJR4BweHQyGr25+KPToK6JgwMjISc9Eu8TvIlGA6Kn5ttCucPXsW4eHhAq6trS1iY2Nx9+7dE5/pOgF5f3V9GGQCSom7cOEC+vr6BAT6uaqq6lDI6vYnCJQ8OkNppwgLCxMJ/B3k5ORkvHr1Cj09PeLam5ubGBkZgYeHBz5+/IiLFy/ix48faGhoQExMjCgsx8fHOcn/BpkqW29vbwwNDYmEEAQqwJqamg6FrG7/gIAAAYWOgcHBQXENGpuSkqIyb3Nzs6gX6HGwq6tLFFuvX78WYKlQe/LkifiOzmhnZ2fQQlheXhbFGM07PT29N54mpp3gxo0bQsufbKdqu/4dZHrGpOdkSlldXZ2ovmlbfP78Oby8vA5A1qR/W1ubAEONCjt6vCMAtJhcXFz25iZIrq6u4rp0BtOWTsUgNbqf6upqXL16VRSL9Knc+umeS0pKBGTleJrbwMAALS0tuH79+p9k/P98q5EAbmxsHDiLj3JKnf70HE4QbGxsRCG1sLAAU1NTlccomp8esajYUwKkflRH2Nvb48yZM3u3QAUj/QHHzs5OFJLK9uv4P0r378n/kyRrQxhf4x8HGLIEq4EhM2QJHJBAIieZIUvggAQSOckMWQIHJJDISWbIEjgggUROMkOWwAEJJHKSGbIEDkggkZPMkCVwQAKJnGSGLIEDEkjkJDNkCRyQQCInmSFL4IAEEjnJDFkCBySQqJJkCfRKK1GhUOz+BbaftLWDFNYjAAAAAElFTkSuQmCC'/>",
}}
/> */}
<img
alt="Click to edit image"
onClick={EditDiagram.DiagramEditor.editElement(this)}
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHkAAAA9CAYAAACJM8YzAAADT3RFWHRteGZpbGUAJTNDbXhmaWxlJTIwaG9zdCUzRCUyMmVtYmVkLmRpYWdyYW1zLm5ldCUyMiUyMG1vZGlmaWVkJTNEJTIyMjAyMS0wMS0xMVQxMCUzQTQxJTNBMzQuMjQ4WiUyMiUyMGFnZW50JTNEJTIyNS4wJTIwKE1hY2ludG9zaCUzQiUyMEludGVsJTIwTWFjJTIwT1MlMjBYJTIwMTFfMV8wKSUyMEFwcGxlV2ViS2l0JTJGNTM3LjM2JTIwKEtIVE1MJTJDJTIwbGlrZSUyMEdlY2tvKSUyMENocm9tZSUyRjg3LjAuNDI4MC44OCUyMFNhZmFyaSUyRjUzNy4zNiUyMiUyMGV0YWclM0QlMjJtNXI1QVhFdDE3eWx2WWlEWXo5UyUyMiUyMHZlcnNpb24lM0QlMjIxNC4xLjklMjIlMjB0eXBlJTNEJTIyZW1iZWQlMjIlM0UlM0NkaWFncmFtJTIwaWQlM0QlMjJlbVlSU0REUmtEUDJZZDNFWnkzciUyMiUyMG5hbWUlM0QlMjJQYWdlLTElMjIlM0VqWkxOVG9Rd0VJQ2ZwbGV6MEloNkZkZjE0Z2tUejVXT3ROblNrbElXOE9sdDdWUm9OaVplWU9hYjZmd1RXdmZMeWJKQnZCb09pcFFIdmhENlJNcXlxS283JTJGd3RramVTV1BrVFFXY2tqT215Z2tWJTJCQUx4T2RKSWNSV1VUT0dPWGtrTVBXYUEydHl4aXoxc3k1MjZkUmVkYUJkWkI1Qk5DMFRGM1RkOG1kaVBTJTJCckRiJTJCQXJJVEtYTlJZWDhmckQxMzFrd2E4Mm1qSVZwNmxzSmdEYU5nM013N1JJJTJCRTF0WVlGNlYlMkJxVUdGc2VZVGUlMkY3RGlpV1BiazFOcEZvdGFQZXZDS21KQzFNVHhuZ1RjZ3d1NGNQQ0ZtQjBOMWVaWmlFZE5BTnJnejc3a3lEMFViaGVlYTN3NG5VaFdPd0ZySU5saDdDd0U1Z2VuRjI5QzFyVDBOWmNuYmZsRkltSjNXSXFaQXp2b2ZzTnZNM0JDemlLcEc0NyUyQkxIdGJwd2V2d0UlM0QlM0MlMkZkaWFncmFtJTNFJTNDJTJGbXhmaWxlJTNFoE8CRAAABV1JREFUeF7tm1lIlVsYht+NXoSipGkIGpoDBYqiKIIQSCiRSigOCV2odZuSw51KoYaR8xCkGDmiaCDiVM5JSQiKoSiFaVk5UoKK4nz4Fmd73KmdvZX28ez1rZst7rXW/7/vs961vl/8FQB2wU2nHVAQ5J2dHZ0WKbM4PT29XQF5d5fDrIsLgbgyZF0ku08TQ9ZxwCSPITNkCRyQQCInmSFL4IAEEjnJDFkCBySQyElmyBI4IIFETjJDlsABCSRykhmyBA5IIJGTzJAlcEACiZxkhiyBAxJI5CQzZAkckEAiJ5khS+CABBJPTZLpRra3t6Gvry+B7dqVqDXI379/h5WV1ZHq2tvbERUVha9fvx7o8+DBA3z+/BmlpaVquaNpf7UmBfDlyxf09/cjNDRU3SEq/U46/lgX1eZ/a1JK5+bmxH2+f/8efn5+4tPMzEz8bnR09EjIk5OTWF9fx+XLl9XSqWl/tSYF0NjYiHv37uHTp0/qDlHpd9Lxx7qoNiHvv8GBgQG4u7tjfn4e5ubm4quOjg7cunULd+7cQUVFBc6fP4+ioiLR79mzZ5idnUViYiLq6+uRn58PmiMwMBCFhYUwNjZW0a9pfxqcnp6OyspKbG1twd/fHxkZGfTWwd68tHB8fHwwMTGB4OBgvHjxQqQ6ISEBHz58wLVr15CTk4Nz585hcXERtJvU1NSIRfzo0SM4OTkdGH9caJqO09p2rQ5kX19fBAUF4fbt28Iwejeru7sb9+/fB5mcnZ0tFkVtbS1MTEwQHx+PiIgIxMXFqejWtP/w8LAAUFxcLOal7fjp06fiXpRtdXUVeXl5yM3NRWtrKywtLWFhYYHo6GiEhITg8ePHWFpaQm9vLzIzM8WiffjwIV6+fImkpCT8/PlTzKkc7+bmpimrY/c/dZBXVlZgaGgojLx586YwTgktLS0N1tbWKCgoQGRkpDBubW0Nly5dOhSyuv3HxsZE+jw9PfHt2zcBmdJM193f9m+3BCsrKwtTU1NQKBQizXSczMzMIDU1Fe/evUNZWRkcHR3x9u1bENTOzs4TbffHpXyqINN2rTy337x5gytXrohXPJSQy8vLhbG0RVIjEJR4BweHQyGr25+KPToK6JgwMjISc9Eu8TvIlGA6Kn5ttCucPXsW4eHhAq6trS1iY2Nx9+7dE5/pOgF5f3V9GGQCSom7cOEC+vr6BAT6uaqq6lDI6vYnCJQ8OkNppwgLCxMJ/B3k5ORkvHr1Cj09PeLam5ubGBkZgYeHBz5+/IiLFy/ix48faGhoQExMjCgsx8fHOcn/BpkqW29vbwwNDYmEEAQqwJqamg6FrG7/gIAAAYWOgcHBQXENGpuSkqIyb3Nzs6gX6HGwq6tLFFuvX78WYKlQe/LkifiOzmhnZ2fQQlheXhbFGM07PT29N54mpp3gxo0bQsufbKdqu/4dZHrGpOdkSlldXZ2ovmlbfP78Oby8vA5A1qR/W1ubAEONCjt6vCMAtJhcXFz25iZIrq6u4rp0BtOWTsUgNbqf6upqXL16VRSL9Knc+umeS0pKBGTleJrbwMAALS0tuH79+p9k/P98q5EAbmxsHDiLj3JKnf70HE4QbGxsRCG1sLAAU1NTlccomp8esajYUwKkflRH2Nvb48yZM3u3QAUj/QHHzs5OFJLK9uv4P0r378n/kyRrQxhf4x8HGLIEq4EhM2QJHJBAIieZIUvggAQSOckMWQIHJJDISWbIEjgggUROMkOWwAEJJHKSGbIEDkggkZPMkCVwQAKJnGSGLIEDEkjkJDNkCRyQQCInmSFL4IAEEjnJDFkCBySQqJJkCfRKK1GhUOz+BbaftLWDFNYjAAAAAElFTkSuQmCC"
/>
{/* <Tester /> */}
</Box>
<Box sx={{ my: 3 }}>
<Typography color="textPrimary" variant="h4">
Scenario
</Typography>
<Typography color="textSecondary" gutterBottom variant="body2">
Enter scenarios
</Typography>
</Box>
<SetScenario countList={countList} />
<Box
sx={{
alignItems: "center",
display: "flex",
ml: -1,
}}
></Box>
{Boolean(formik.touched.policy && formik.errors.policy) && (
<FormHelperText error>{formik.errors.policy}</FormHelperText>
)}
<Box
sx={{
py: 2,
display: "flex",
justifyContent: "flex-end",
justifyContent: "space-between",
}}
>
<Box>
<Button
color="primary"
disabled={formik.isSubmitting}
size="large"
variant="contained"
onClick={AddScenario}
sx={{
marginRight: 1,
}}
>
Add Row
</Button>
<Button
color="primary"
disabled={formik.isSubmitting}
size="large"
variant="contained"
onClick={DeleteScenario}
>
Delete Row
</Button>
</Box>
<NextLink href="/requirements" passHref>
<Button
color="primary"
disabled={formik.isSubmitting}
size="large"
type="submit"
variant="contained"
>
Submit
</Button>
</NextLink>
</Box>
</form>
</Container>
</Box>
</>
);
};
WorkArea.getLayout = (page) => <DashboardLayout>{page}</DashboardLayout>;
export default WorkArea;

Javascript array slicing based on filter

I'm stuck on writing out logic that will show more comments if user clicks show more comments.
How would i go about performing this logic that filters based on the following: initially there are 2 comments that show(out of 7 total comments). I want to break this down as user keeps clicking on show more. Should show 5 more comments, 3 more comments, 1 more comment, until there is no more comments.
I'm not too sure on what im doing.
CommentList.tsx
import React, { Fragment, useState } from "react";
import Grid from "#material-ui/core/Grid";
import List from "#material-ui/core/List";
import Typography from "#material-ui/core/Typography";
import CommentItem from "./../commentItem/CommentItem";
import moment from "moment";
import OurLink from "../../../common/OurLink";
import OurSecondaryButton from "../../../common/OurSecondaryButton";
import OurModal from "../../../common/OurModal";
const ourStyle = {
backgroundColor: "#FAFAFA",
border: "1px solid #f2f2f2",
borderRadius: "4px",
padding: "15px 20px",
margin: "15px",
};
function CommentList(props: any) {
const [showMore, setShowMore] = useState<Number>(2);
const [openModal, setOpenModal] = useState(false);
const [showLessFlag, setShowLessFlag] = useState<Boolean>(false);
const lastIndexOfComments = props.comments.length - 1;
const startIndex = 0;
console.log(lastIndexOfComments);
const showComments = (e) => {
e.preventDefault();
const subtract = props.comments.length - 2 ;
console.log("testing", subtract);
setShowMore(subtract);
// setShowLessFlag(true);
};
const handleClickOpen = () => {
setOpenModal(true);
};
const handleCloseModal = () => {
setOpenModal(false);
};
.....
const showMoreComments = () => {
return props.comments
.slice(startIndex, showMore)
.sort((a, b) => a.id - b.id)
.map((comment, i) => (
<div key={i}>
<List style={{ paddingBottom: "20px" }}>
<img alt="gravatar" style={{ margin: "-10px 15px" }} src={comment.author.gravatar} width="30" height="30" />
<Typography style={{ display: "inline-block", fontWeight: 700, padding: "5px 0px" }} variant="h6" align="left">
{Object.entries(props.currentUser).length === 0 ? (
<Fragment>
<span style={{ cursor: "pointer", fontSize: "12px", fontWeight: isBold(comment) }} onClick={handleClickOpen}>
{comment.author.username}
</span>
{comment.userId === props.userId && <span style={{ fontSize: "12px" }}> (OP)</span>}
{openModal ? <OurModal open={openModal} handleClose={handleCloseModal} /> : null}
</Fragment>
) : (
<Fragment>
<OurLink
style={{ fontSize: "12px", fontWeight: isBold(comment) }}
to={{
pathname: `/profile/${comment.author.username}`,
}}
title={comment.author.username}
/>
{comment.userId === props.userId && <span style={{ fontSize: "12px" }}> (OP)</span>}
</Fragment>
)}
</Typography>
<div style={ourStyle}>
<CommentItem comment={comment} user={props.user} postId={props.postId} {...props} />
<Typography style={{ fontSize: "12px" }} variant="body1" align="left">
{moment(comment.createdAt).calendar()}
</Typography>
</div>
</List>
</div>
));
};
const ourComments = props.comments;
console.log("before comments", ourComments);
console.log("fsfsfsftestingcomments", ourComments.slice(0, showMore));
return (
<Grid>
<Fragment>
<div style={{ margin: "30px 0px" }}>
<OurSecondaryButton onClick={(e) => showComments(e)} component="span" color="secondary">
View More Comments
</OurSecondaryButton>
</div>
</Fragment>
{showLessFlag === true ? (
// will show most recent comments below
showMoreComments()
) : (
<Fragment>
{/* filter based on first comment */}
{props.comments
.filter((item, i) => item)
.sort((a, b) => b.id - a.id)
.slice(startIndex, showMore)
.map((comment, i) => (
<div key={i}>
<List style={{ paddingBottom: "20px" }}>
<img alt="gravatar" style={{ margin: "-10px 15px" }} src={comment.author.gravatar} width="30" height="30" />
<Typography style={{ display: "inline-block", fontWeight: 700, padding: "5px 0px" }} variant="h6" align="left">
{Object.entries(props.currentUser).length === 0 ? (
<Fragment>
<span style={{ fontSize: "12px", cursor: "pointer", fontWeight: isBold(comment) }} onClick={handleClickOpen}>
{comment.author.username}
{comment.userId === props.userId && <span style={{ fontSize: "12px" }}> (OP)</span>}
</span>
{openModal ? <OurModal open={openModal} handleClose={handleCloseModal} /> : null}
</Fragment>
) : (
<Fragment>
<OurLink
style={{ fontSize: "12px", fontWeight: isBold(comment) }}
to={{
pathname: `/profile/${comment.author.username}`,
}}
title={comment.author.username}
/>
{comment.userId === props.userId && <span style={{ fontSize: "12px" }}> (OP)</span>}
</Fragment>
)}
</Typography>
<div style={ourStyle}>
<CommentItem comment={comment} user={props.user} postId={props.postId} {...props} />
<Typography style={{ fontSize: "12px" }} variant="body1" align="left">
{moment(comment.createdAt).calendar()}
</Typography>
</div>
</List>
</div>
))}
</Fragment>
)}
</Grid>
);
}
// prevents un-necesary re renders
export default React.memo(CommentList);
If you have all comments already fetched, you could simply set a limit and only show the comments with an index lower than the limit.
Check this out: https://stackoverflow.com/a/44071932/10955418

Using Constructor(props) without Class Component

I have created a search bar in TypeScript but for now I am unable to type anything into it. All the control component tutorials that I have seen suggest to use constructor(props) or so. If I use it in my code, I get errors.
Is there any way to use it without having a class component?
For instance, I am using a const() for my page. Is there any way I can make the search bar of this functional?
const userSearchPage = () => (
<div>
<PermanentDrawerLeft></PermanentDrawerLeft>
<div className='main-content'>
<MuiThemeProvider>
<DropDownMenu >
<MenuItem style={{ fontSize: "20px" }} primaryText="Search By" />
<MenuItem value={1} style={{ fontSize: "20px" }} primaryText="First Name" />
<MenuItem value={1} style={{ fontSize: "20px" }} primaryText="Last Name" />
</DropDownMenu>
</MuiThemeProvider>
<SearchBar
onChange={() => console.log('onChange')}
onRequestSearch={() => console.log('onRequestSearch')}
style={{
margin: '0 auto',
maxWidth: 800
}}
/>
</div>
</div>
);
You must use the useState hook in a functional component.
const userSearchPage = () => {
const [value, setValue] = React.useState('');
return (
<div>
<PermanentDrawerLeft></PermanentDrawerLeft>
<div className='main-content'>
<MuiThemeProvider>
<DropDownMenu >
<MenuItem style={{ fontSize: "20px" }} primaryText="Search By" />
<MenuItem value={1} style={{ fontSize: "20px" }} primaryText="First Name" />
<MenuItem value={1} style={{ fontSize: "20px" }} primaryText="Last Name" />
</DropDownMenu>
</MuiThemeProvider>
<SearchBar
onChange={(value) => setValue(value) }
value={value}
onRequestSearch={() => console.log('onRequestSearch')}
style={{
margin: '0 auto',
maxWidth: 800
}}
/>
</div>
</div>
)} ;
Props in functional component's are simply parameters!
function SearchBar (props) {
let searchbartext = document.getElementById('searchbartext')
searchbartext.addEventListener('change', (e) => {
props.onChange(e)
}
return (
<form onsubmit={(e) => props.onRequestChange(e)}>
<input id="searchbartext" style={props.style} />
</form>
)
}
const UserSearchPage = () => {
function onRequestSearch (e) {
console.log.('request search', e)
}
function onChange(e) {
console.log('onChange')
}
return (
{SearchBar({
onChange:onChange,
onRequestSearch:onRequestSearch,
style:{
margin: '0 auto',
maxWidth: 800
}
})}
)
}
Edit: you also have to call functional component's as functions, not with <> syntax like class components. I used the term "props" inside SearchBar(props) but it's just following Reacts naming convention. You could just as easily replace it with SearchBar(bananas).

How to split material-ui toolbar into left and right part

How to split material-ui toolbar into left and right part. For example, this is my toolbar
let EnhancedTableToolbar = props => {
const { numSelected, classes ,deletefunc} = props;
return (
<Toolbar
className={classNames(classes.root, {
[classes.highlight]: numSelected > 0,
})}
>
<div className={classes.title}>
{numSelected > 0 ? (
<Typography color="inherit" variant="subtitle1">
{numSelected} selected
</Typography>
) : (
<Typography variant="h6" id="tableTitle">
User List
</Typography>
)}
</div>
<div className={classes.actions}>
{numSelected > 0 ? (
<div >
<div style={{ display: 'inline-block' }}>
<Tooltip title="Delete">
<IconButton aria-label="Delete">
<DeleteIcon onClick={() => { if (window.confirm('Are you sure you wish to delete '+numSelected +' item?')) {deletefunc()} } }>
</DeleteIcon>
</IconButton>
</Tooltip>
</div>
<div style={{ display: 'inline-block' }}>
<Tooltip title="Edit">
<IconButton aria-label="Edit">
<EditIcon>
</EditIcon>
</IconButton>
</Tooltip>
</div>
</div>
) : (
<Tooltip title="Filter list">
<IconButton aria-label="Filter list">
<FilterListIcon />
</IconButton>
</Tooltip>
)}
</div>
</Toolbar>
);
};
I want to show the numSelected in my left side of toolbar and the delete button and edit button at my right side of toolbar. However, my example output show the delete button and edit button just beside the numSelected. Anyone has any solution regarding this issue?
The solution is add
flex: '0 0 auto'
in my actions class and a
<div className={classes.spacer}>
between title class and action class.
This is how I setup spacer, title and action classes.
const toolbarStyles = theme => ({
root: {
paddingRight: theme.spacing.unit,
},
highlight:
theme.palette.type === 'light'
? {
color: theme.palette.secondary.main,
backgroundColor: lighten(theme.palette.secondary.light, 0.85),
}
: {
color: theme.palette.text.primary,
backgroundColor: theme.palette.secondary.dark,
},
spacer: {
flex: '1 1 100%',
},
actions: {
color: theme.palette.text.secondary,
flex: '0 0 auto',
},
title: {
flex: '0 0 auto',
},
});

Categories

Resources