How to set json data to footer list react - reactjs

I start working with react and i need to set mock json data to list in footer.
How i can set list dynamically to each module. I have 3 modules Company, Catalog, Contacts, and JSON:
const FOOTER_DATA = {
menu: {
title: "Company",
items: [
{
title: "Link 1",
link: "#",
},
{
title: "Link 2",
link: "#",
}
],
},
catalog: {
title: "Catalog",
items: [
{
title: "Link Link 1",
link: "#",
},
{
title: "LinkLink 2",
link: "#",
},
{
title: "LinkLink 3",
link: "#",
},
{
title: "LinkLink 4",
link: "#",
},
{
title: "LinkLink 5",
link: "#",
},
{
title: "LinkLink 6",
link: "#",
}
],
},
contact: {
email: "some-mail#gmail.com",
tel: "777 777 777",
work_time: {
weekdays: "09:00 - 18:00",
weekends: "10:00 - 16:00",
},
},
};
How i can set this for each jsx file, to special tags:
<Company />
<Categories />
<Contacts />
I am really beginner in react an i stuck in such issues.

You should pass the data as a prop to each element and render the data inside each component.
<Company data={FOOTER_DATA?.menu}/>
<Categories data={FOOTER_DATA?.catalog}/>
<Contacts data={FOOTER_DATA?.contact}/>
For example you may have a JSX component for Company like below,
import React from "react";
const Company = ({ data }) => {
return (
<React.Fragment>
<h2>{data.title}</h2>
{data.items.map((item, index) => (
<a key={index} href={item.link}>
{item.title}
</a>
))}
</React.Fragment>
);
};
export default Company;

Related

With react DnD, why my state resets when every time I drop an element?

I am working on a form builder. The basic implementation works but every time when I move elements from the tool box to the form the current state resets to initial then add newly dropped element so previously dragged element is missed from the form. Below is the linked to the source code at sandbox.
https://codesandbox.io/s/nifty-https-qx8lko
index.js
import Example from "./Example.jsx";
import { DndProvider } from "react-dnd";
import { HTML5Backend } from "react-dnd-html5-backend";
import "./style.sass";
function App() {
return (
<div className="App">
<DndProvider backend={HTML5Backend}>
<Example />
</DndProvider>
</div>
);
}
const rootElement = document.getElementById("root");
render(<App />, rootElement);
Example.jsx
import React, { useState } from "react";
import Form from "./Form";
import Toolbar from "./Toolbar";
const Example = (props) => {
const [Items, setItems] = useState([{ name: "Test" }]);
const addItem = (item) => {
setItems([...Items, item]);
};
return (
<div className="card" style={{ border: "1px dashed rgb(219 163 163)" }}>
<div className="card-header d-flex justify-content-between">
<h5 className="cart-title m-0">View</h5>
</div>
<div className="card-body">
<div className="row">
<div className="col-9">
<Form items={Items} addItems={addItem} />
</div>
<div className="col-3">
<Toolbar />
</div>
</div>
</div>
</div>
);
};
export default Example;
Form.jsx
import React from "react";
import { useDrop } from "react-dnd";
import { ItemTypes } from "./ItemTypes";
function Form(props) {
const addItem = (item) => {
props.addItems(item);
};
const [{ canDrop, isOver }, drop] = useDrop(() => ({
accept: ItemTypes.CARD,
drop: (item, monitor) => addItem(item),
collect: (monitor) => ({
isOver: monitor.isOver(),
canDrop: monitor.canDrop()
})
}));
return (
<div className="card card-default shadow-sm mt-3">
<div className="card-body">
{props.items.map((item, index) => {
return (
<div key={index} className="form-item">
{item.name}
</div>
);
})}
<div ref={drop}>
{/* {canDrop ? "Release to drop" : "Drag a box here"} */}
{isOver && canDrop && (
<div className="form-place-holder">
<div>Release to Drop</div>
</div>
)}
{!isOver && (
<div className="form-place-holder">
<div>Dropzone</div>
</div>
)}
</div>
</div>
</div>
);
}
export default Form;
Toolbar.jsx
import React from "react";
import ToolbarItem from "./ToolbarItem";
const Toolbar = () => {
const _defaultItems = () => {
return [
{
key: "Header",
name: "Header Text",
icon: "fas fa-heading",
static: true,
content: "Place holder text"
},
{
key: "Label",
name: "Label",
static: true,
icon: "fas fa-font",
content: "Place holder text"
},
{
key: "Paragraph",
name: "Paragraph",
static: true,
icon: "fas fa-paragraph",
content: "Place holder text"
},
{
key: "LineBreak",
name: "Line break",
static: true,
icon: "fas fa-arrows-alt-h"
},
{
key: "Dropdown",
canHaveAnswer: true,
name: "Dropdown",
icon: "far fa-caret-square-down",
label: "Place holder label",
field_name: "dropdown_",
options: []
},
{
key: "Tags",
canHaveAnswer: true,
name: "Tags",
icon: "fas fa-tags",
label: "Place holder label",
field_name: "tags_",
options: []
},
{
key: "Checkboxes",
canHaveAnswer: true,
name: "Checkboxes",
icon: "far fa-check-square",
label: "Place holder label",
field_name: "checkboxes_",
options: []
},
{
key: "RadioButtons",
canHaveAnswer: true,
name: "Multiple choices",
icon: "far fa-dot-circle",
label: "Place holder label",
field_name: "radiobuttons_",
options: []
},
{
key: "TextInput",
canHaveAnswer: true,
name: "Text input",
label: "Place holder label",
icon: "fas fa-font",
field_name: "text_input_"
},
{
key: "NumberInput",
canHaveAnswer: true,
name: "Number input",
label: "Place holder label",
icon: "fas fa-plus",
field_name: "number_input_"
},
{
key: "TextArea",
canHaveAnswer: true,
name: "Multi line input",
label: "Place holder label",
icon: "fas fa-text-height",
field_name: "text_area_"
},
{
key: "TwoColumnRow",
canHaveAnswer: false,
name: "Two columns row",
label: "",
icon: "fas fa-columns",
field_name: "two_col_row_"
},
{
key: "ThreeColumnRow",
canHaveAnswer: false,
name: "Three columns row",
label: "",
icon: "fas fa-columns",
field_name: "three_col_row_"
},
{
key: "FourColumnRow",
canHaveAnswer: false,
name: "Four columns row",
label: "",
icon: "fas fa-columns",
field_name: "four_col_row_"
},
{
key: "Image",
name: "Image",
label: "",
icon: "far fa-image",
field_name: "image_",
src: ""
},
{
key: "Rating",
canHaveAnswer: true,
name: "Rating",
label: "Place holder label",
icon: "fas fa-star",
field_name: "rating_"
},
{
key: "DatePicker",
canDefaultToday: true,
canReadOnly: true,
dateFormat: "MM/dd/yyyy",
timeFormat: "hh:mm aa",
showTimeSelect: false,
showTimeSelectOnly: false,
showTimeInput: false,
name: "Date",
icon: "far fa-calendar-alt",
label: "Place holder label",
field_name: "date_picker_"
},
{
key: "Signature",
canReadOnly: true,
name: "Signature",
icon: "fas fa-pen-square",
label: "Signature",
field_name: "signature_"
},
{
key: "HyperLink",
name: "Website",
icon: "fas fa-link",
static: true,
content: "Place holder website link",
href: "http://www.example.com"
},
{
key: "Download",
name: "File attachment",
icon: "fas fa-file",
static: true,
content: "Place holder file name",
field_name: "download_",
file_path: "",
_href: ""
},
{
key: "Range",
name: "Range",
icon: "fas fa-sliders-h",
label: "Place holder label",
field_name: "range_",
step: 1,
default_value: 3,
min_value: 1,
max_value: 5,
min_label: "Easy",
max_label: "Difficult"
},
{
key: "Camera",
name: "Camera",
icon: "fas fa-camera",
label: "Place holder label",
field_name: "camera_"
},
{
key: "FileUpload",
name: "File upload",
icon: "fas fa-file",
label: "Place holder label",
field_name: "file_upload_"
}
];
};
return (
<div className="react-form-builder-toolbar">
<h4>Toolbox</h4>
<ul>
{_defaultItems().map((item, index) => {
return <ToolbarItem data={item} key={index} />;
})}
</ul>
</div>
);
};
export default Toolbar;
ToolbarItem.jsx
import React from "react";
import { useDrag } from "react-dnd";
import { ItemTypes } from "./ItemTypes";
function ToolbarItem(props) {
const data = props.data;
const [{ isDragging }, drag, dragPreview] = useDrag(() => ({
type: ItemTypes.CARD,
collect: (monitor) => ({
isDragging: monitor.isDragging()
}),
item: props.data
}));
return (
<li ref={drag} style={{ opacity: isDragging ? 0.5 : 1 }}>
<i className={data.icon}></i>
{data.name}
</li>
);
}
export default ToolbarItem;
I have tried also storing the state in redux and still same behavior. For simplicity I have kept the state in parent component in Sandbox example.
In Example.js file try replacing with this setItems((items)=>[...items, item]);
I think this will fix the issue. Check this here https://codesandbox.io/s/reactjs-dnd-example-forked-1lu5i9?file=/src/Form.jsx

Style Mapped Material-UI Icons with the Same Styles (React)

Without adding a className or style tag to each object with a material-ui icon element, what's the best way to style each icon if each icon has the same style?
const btns = [
{ name: "test1", icon: <Icon1 />, link: "test1" },
{ name: "test2", icon: <Icon2 />, link: "test2" },
{
name: "test3",
icon: <Icon3 />,
link: "test3",
},
{ name: "test4", icon: <Icon4 />, link: "test4" },
{ name: "test5", icon: <Icon5 />, link: "test5" },
{ name: "test6", icon: <Icon6 />, link: "test6" },
{ name: "test7", icon: <Icon7 />, link: "test7" },
{ name: "test8", icon: <Icon8 /> },
];
const LeftNav = () => {
const classes = useStyles();
return (
<div className="leftNavContainerStyle">
{btns.map((btn) => {
return (
<Button className={classes.navBtnContainer} color="primary">
{btn.icon} //add the same style to each icon.
{btn.name}
</Button>
);
})}
</div>
);
};
export default LeftNav;
Ive tried changing each icon key to: { name: "test1", icon: Icon1, link: "test1" }, and then changing btn.icon to <btn.icon/> and adding a style like <btn.icon style={styles}/>, but this errors out.
Any help would be appreciated!
You could use the React.cloneElement function and then just pass in the style when it gets cloned. So something like this
{btns.map((btn) => {
return (
<Button className={classes.navBtnContainer} color="primary">
{React.cloneElement(btn.icon, {
// pass in any new props into this object
className={...}
})}
{btn.name}
</Button>
);
})}
Finally figured it out,
import { SvgIcon } from "#material-ui/core"; //import SvgIcon
const btns = [
{ name: "test1", icon: Icon1, link: "test1" },//remove tags from icon components
{ name: "test2", icon: Icon2, link: "test2" },
{
name: "test3",
icon: Icon3,
link: "test3",
},
{ name: "test4", icon: Icon4, link: "test4" },
{ name: "test5", icon: Icon5, link: "test5" },
{ name: "test6", icon: Icon6, link: "test6" },
{ name: "test7", icon: Icon7, link: "test7" },
{ name: "test8", icon: Icon8 },
];
const LeftNav = () => {
const classes = useStyles();
return (
<div className="leftNavContainerStyle">
{btns.map((btn) => {
return (
<Button className={classes.navBtnContainer} color="primary"> //use the component from SvgIcon
<SvgIcon component={btn.icon} className="whateverclassyouwant" />
{btn.name}
</Button>
);
})}
</div>
);
};
export default LeftNav;

react-i18next issue translating json values from translation file

I'm developing a multilanguage site and in several sections I use a hardcoded json to store some clients details (name, logo, project description and website) and then I map the json file and print the details using a component nothing fancy.
The problem is that I'm trying to set multilanguage and I don't know why when I try to set translated values to the json is not working. This is how I'm trying it now:
This is my react component:
import { useTranslation } from "react-i18next";
const { t } = useTranslation();
const companyADescription = t("projects.companyA.name");
{
name: "Company A",
url: "company.com",
image: "/assets/projects/a.png",
technologies: [
{
icon: "/assets/tech/react.png",
link: "#",
alt: "",
},
{
icon: "/assets/tech/firebase.png",
link: "#",
alt: "",
},
],
description: t("project.companyA.name"),
},
{
name: "Company B",
url: "company.com",
image: "/assets/projects/b.png",
technologies: [
{
icon: "/assets/tech/react.png",
link: "#",
alt: "",
},
{
icon: "/assets/tech/firebase.png",
link: "#",
alt: "",
},
],
description: t("projects.companyB.name"),
},
And this is my json file with the translation:
"projects": {
"companyA": {
"name": "Company A Project",
"description": "This is the company project description A"
}
}
On other sections I use the t function from the useTranslation hook and works well I already spent a lot of time on this issue :(
The problem is here
description: t("project.companyA.name")
The function isnt being called
You can try this above declaration of JSON
const descriptionA = t("project.companyA.name")
const descriptionB = t("projects.companyB.name")
And then assign the values in JSON as
{
name: "Company A",
url: "company.com",
image: "/assets/projects/a.png",
technologies: [
{
icon: "/assets/tech/react.png",
link: "#",
alt: "",
},
{
icon: "/assets/tech/firebase.png",
link: "#",
alt: "",
},
],
description: descriptionA ,
},
{
name: "Company B",
url: "company.com",
image: "/assets/projects/b.png",
technologies: [
{
icon: "/assets/tech/react.png",
link: "#",
alt: "",
},
{
icon: "/assets/tech/firebase.png",
link: "#",
alt: "",
},
],
description: descriptionB ,
},

TypeScript: Property 'icon' does not exist on type 'JSX.IntrinsicElements'

Hello I'm trying to use typescript with react-icons as follows:
import { IconType } from 'react-icons';
import { FiAlertOctagon } from 'react-icons/fi';
export interface IDropdownItems {
name: string;
link: string;
}
export interface ITag {
name: string;
link: string;
icon: IconType;
dropdownItems: IDropdownItems[] | null;
active: boolean;
}
export const SideBarTags: ITag[] = [
{
name: 'Tutoriais',
link: '../tutorials',
icon: FiAlertOctagon,
dropdownItems: null,
active: false,
},
{
name: 'Avisos',
link: '../news',
icon: FiAlertOctagon,
dropdownItems: null,
active: false,
},
{
name: 'Serviços',
link: '../services',
icon: FiAlertOctagon,
active: false,
dropdownItems: [
{ name: 'Elo Boost', link: '/eloBost' },
{ name: 'Duo Boost', link: '/duoBoost' },
{ name: 'MD10', link: '/eloBost' },
{ name: 'Coaching', link: '/duoBoost' },
{ name: 'Vitóriais', link: '/duoBoost' },
],
},
{
name: 'Carteira',
link: '../cartcredit',
icon: FiAlertOctagon,
active: false,
dropdownItems: [
{ name: 'Histórico', link: '/history' },
{ name: 'Adicionar Crédito', link: '/add' },
],
},
];
and did the following in tsx:
<a>
<icon />
<span className="li-name">{name}</span>
</a>
but i got this erros:
Property 'icon' does not exist on type 'JSX.IntrinsicElements'.
TS2339
I can't seem to find the right way to do this
I'm not able to find the correct way to do this, how I could pass an icon or its name through my array and render in tsx
In JSX, lower case tags are used for the built in elements like <div> <a> or <span>, and it's complaining that <icon> is not one of those. For custom components, you need to use an upper case letter. If you're receive a prop that's in lower case that's fine, but you'll need to rename it before using it for a jsx tag. For example:
const Example = (props) => {
const Icon = props.icon;
return (
<a>
<Icon />
<span className="li-name">{name}</span>
</a>
)
}

Passing array of arrays as props

Can someone explain what I am doing wrong here....
<Something
content={[
{
heading: "Add Company",
icon: "plus",
options: {[
{
image: "srcimage",
text: "New Company",
link: "test"
}, { //Errors here
image: "srcimage",
text: "Existing Company",
link: "test"
}
]}
}, {
heading: "Import Company",
icon: "download",
options: {[
{
image: "/src/image",
text: "Class",
link: "/test"
},
{
image: "/src/image",
text: "BGL",
link: "/test"
},
{
image: "/src/image",
text: "SuperMate",
link: "/test"
}
]}
}]
} />
I get the error... Unexpected token, expected "]" where it says error here. Eventually I would like to create some blocks of content based on whats passed in like this....
Thanks
{[]} isn't valid syntax for an object.
content={[
{
heading: "Add Company",
icon: "plus",
options: [ // remove the curly boy that was here
{
image: "srcimage",
text: "New Company",
link: "test"
}, {
image: "srcimage",
text: "Existing Company",
link: "test"
}
] // and here
}, {
heading: "Import Company",
icon: "download",
options: [ // and here
{
image: "/src/image",
text: "Class",
link: "/test"
},
{
image: "/src/image",
text: "BGL",
link: "/test"
},
{
image: "/src/image",
text: "SuperMate",
link: "/test"
}
] // and here
}]}
For the options properties you need to remove the curly braces, just pass the array
options: [
{
image: "srcimage",
text: "New Company",
link: "test"
},
{
image: "srcimage",
text: "Existing Company",
link: "test"
}
]

Resources