I used controls as an array here. What are some other options to pass the multiple property values as I used from 3 to 4 times in this array?
import React from "react";
import BuildControl from "./BuildControl";
import styles from "./BuildControls.module.css";
const controls = [
{ label: "Salad", type: "salad" },
{ label: "Bacon", type: "bacon" },
{ label: "Cheese", type: "cheese" },
{ label: "Meat", type: "meat" },
];
const buildControls =(props)=>(
<div className={styles.BuildControls}>
{controls.map(cntrl => (
<BuildControl key={cntrl.label} type={cntrl.label}/>
))}
</div>
);
export default buildControls;
If I understand your problem, it's just a style problem ?
You can do like this:
const buildControls =(props)=>(
<div className={styles.BuildControls}>
{controls.map(({ label }) => (
<BuildControl key={label} type={label}/>
))}
</div>
);
You unpack the object value directly in the function parameters
Related
im triying to select by default a value into a select input but the input is not recognizing that value until i change it manually. By the default i set "All" as my default value. here is my code and the codesandbox link:
import "./styles.css";
import React, { useState, useEffect } from "react";
import { FormField } from "react-form-input-fields";
import "react-form-input-fields/dist/index.css";
export default function App() {
let [type, setType] = useState("All");
const types = [
{ label: "All", value: "All" },
{ label: "Afganistan", value: "Afganistan" },
{ label: "Albania", value: "Albania" },
{ label: "Algeria", value: "Algeria" },
{ label: "American Samoa", value: "American Samoa" },
{ label: "Andorra", value: "Andorra" },
{ label: "Angola", value: "Angola" }
];
function handletype(e) {
setType(e);
}
return (
<div className="App">
{/* <h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2> */}
<FormField
type="select"
value={type}
option={types}
label={"Select your type"}
keys={"label"}
handleOnChange={(value) => handletype(value)}
/>
</div>
);
}
link:
https://codesandbox.io/s/select-problem-ykplcm
The library you use has a bug
The source code reveals that the value prop is only checked in componendDidUpdate, but this hooks is not called for the initial render
I would rather use a different library
I'm creating an interactive viz with React and I would like to add a slider in my viz.
import "./styles.css";
import React from "react";
import Sunburst from "react-zoomable-sunburst";
import { data } from "./data";
import { Slider } from "#mui/material";
class App extends React.Component {
onSelect(event) {
console.log(event);
}
render() {
return (
<div className="App">
<Sunburst
width="400"
height="400"
data={data.a}
count_member="size"
labelFunc={(node) => node.data.name}
_debug={false}
/>
<Slider
aria-label="Year"
defaultValue={2016}
valueLabelDisplay="auto"
step={1}
marks
min={2016}
max={2020}
/>
</div>
);
}
}
export default App;
Above is my code. I added my data from 2016 to 2020 in data.js file and I want my viz to change according to the year as I move my slider.
a: {
name: "2020",
children: [
{
name: "Campus",
children: [
{
name: "Liabilities",
children: [
{
name: "Current Liabilities",
children: [
{ name: "Accounts payable", size: 53010 },
{ name: "Accrued salaries", size: 23554 },
{ name: "Unearned revenue", size: 253322 },
{ name: "Commercial paper", size: 326008 },
{ name: "Current portion of long-term debt", size: 112431 },
{ name: "Funds held for others", size: 2500 },
{ name: "Other current liabilities", size: 71036 }
]
}
This is a part of my code in data.js and I named 2016 data as a, 2017 as b, and so on.
I wanted to name as 2016, 2017... instead of a,b... but this didn't work since data.2016 didn't work. (So I made it data.a in the code above)
So currently, my slider doesn't work. Is there any way to make dictionary or other method in React to resolve this problem?
Thanks.
use
data['2016']
That should work.
I'm trying to use an object key to set the name of a column in MUI Datatables.
I'm trying to set one of the column names with the first element of children.childName
so that in that column it will display list of child names, but only the first child.
In Current way that Im trying this, I am getting no errors, and its displaying nothing in the childName Column on the table.
How Can I access an object thats inside an array?
This is my Data:
const data = [
{
name: "Pat",
company: "Test Corp",
city: "Yonkers",
state: "NY",
children: [
{ childName: "Pat Jun", childAge: 2 },
{ childName: "Mary Jun", childAge: 2 }
]
},
];
const columns = [
{
name:name: data[0]["children"][0]["childName"],
label: "Child Name",
options: {
filter: true,
sort: true
}
}]
MuiTable.js
function MuiTable({ forms }) {
console.log("cols", columns);
return (
<MUIDataTable
title={"Title"}
data={data}
columns={columns}
options={options}
/>
);
}
By doing a console.log I can see that it is printing the value instead of the object key name
I would really appreciate any help, Thank you.
You need to use customBodyRender like this:
import React from "react";
import ReactDOM from "react-dom";
import MUIDataTable from "mui-datatables";
import { Typography } from "#material-ui/core";
import "./styles.css";
function App() {
const data = [
{
name: "Pat",
company: "Test Corp",
city: "Yonkers",
state: "NY",
children: [
{ childName: "Pat Jun", childAge: 2 },
{ childName: "Mary Jun", childAge: 2 }
]
}
];
const columns = [
{
name: "children",
label: "Child Names",
options: {
filter: true,
sort: true,
customBodyRender: (value, tableMeta, updateValue) => (
<Typography>
{value.map(child => child.childName).join(",")}
</Typography>
)
}
}
];
return (
<div>
<MUIDataTable title={"Title"} data={data} columns={columns} />
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Thanks very much to #Klaus your answer. That's pretty much what I had to do, but In my case, I wanted to only display the first childName in the object children which was in an array of objects.
So I had to adapt it a bit and change my data structure as well.
This is what I ended up doing.
I first added a simple array to my data structure completely seperate to the array containing the children objects called childNames, which just came contained only the names.
This made it alot easier to access the childNames as it was just a simple array not nested in anything.
So I simply just displayed the first element in the array on Table
const columns = [
{
name: "childNames",
label: "Child Name",
options: {
filter: true,
customBodyRender: (value, tableMeta, updateValue) => {
return <div>{value[0]}</div>;
}
}
},
The reason why I created an array for just childNames, was because trying to access only just the first childName in the array containing children objects was proving very complicated and difficult.
Thanks very much for all the help.
I have a scrolling menu items, and the titles of each item is hardcoded into a const, along side with the id
const list = [
{ name: "category1", id: 0 },
{ name: "category2", id: 1 },
{ name: "category3", id: 2 },
{ name: "category4", id: 3 },
{ name: "category5", id: 4 },
{ name: "category6", id: 5 },
{ name: "category7", id: 6 },
{ name: "category8", id: 7 }
];
I have a json file that contains the category name for each child:
{
"results": [
{
"category": "category1",
"name": {
"title": "mr",
"first": "ernesto",
"last": "roman"
},
"email": "ernesto.roman#example.com",
"id": {
"name": "DNI",
"value": "73164596-W"
},
"picture": {
"large": "https://randomuser.me/api/portraits/men/73.jpg",
"medium": "https://randomuser.me/api/portraits/med/men/73.jpg",
"thumbnail": "https://randomuser.me/api/portraits/thumb/men/73.jpg"
}
},
{
"category": "category2",
"name": {
"title": "mr",
"first": "adalbert",
"last": "bausch"
},
"email": "adalbert.bausch#example.com",
"id": {
"name": "",
"value": null
} etc....
I want to show these categories "category": "category1", as the titles of my menu, I now that I need to start stateless and add them from the JSON, the fetching part from the JSON is done locally in componentDidMount, but I am not sure how can I map them into appearing as menu names to make the menu dynamic, I basically want the same output but from the json not hardcoded. here is a sandbox snippet, would appreciate the help.
https://codesandbox.io/s/2prw4j729p?fontsize=14&moduleview=1
Just convert the JSON output to an object like list with a map function from the results and then set is as MenuItems on the state, which is what you pass to the function on render(). Like that.
import React, { Component } from "react";
import ScrollMenu from "react-horizontal-scrolling-menu";
import "./menu.css";
// One item component
// selected prop will be passed
const MenuItem = ({ text, selected }) => {
return (
<div>
<div className="menu-item">{text}</div>
</div>
);
};
// All items component
// Important! add unique key
export const Menu = list =>
list.map(el => {
const { name, id } = el;
return <MenuItem text={name} key={id} />;
});
const Arrow = ({ text, className }) => {
return <div className={className}>{text}</div>;
};
export class Menucat extends Component {
state = {
selected: "0",
MenuItems: []
};
componentDidMount() {
fetch("menu.json")
.then(res => res.json())
.then(result => {
const items = result.results.map((el, idx) => {
return { name: el.category, id: idx };
});
this.setState({
isLoaded: true,
MenuItems: items
});
});
}
render() {
const { selected, MenuItems } = this.state;
// Create menu from items
const menu = Menu(MenuItems, selected);
return (
<div className="App">
<ScrollMenu
data={menu}
selected={selected}
onSelect={this.onSelect}
alignCenter={true}
tabindex="0"
/>
</div>
);
}
}
export default Menucat;
Cheers!
Looks like you don't have to hard code your category list at all. In your componentDidMount() fetch the json and group the results into separate categories like this:
const json = {
"results": [
{
category: "category1",
name: "Fred"
},
{
category: "category1",
name: "Teddy"
},
{
category: "category2",
name: "Gilbert"
},
{
category: "category3",
name: "Foxy"
},
]
}
const grouped = json.results.reduce((acc, cur) => {
if (!acc.hasOwnProperty(cur.category)) {
acc[cur.category] = []
}
acc[cur.category].push(cur)
return acc;
}, { })
// parent object now has 3 properties, namely category1, category2 and category3
console.log(JSON.stringify(grouped, null, 4))
// each of these properties is an array of bjects of same category
console.log(JSON.stringify(grouped.category1, null, 4))
console.log(JSON.stringify(grouped.category2, null, 4))
console.log(JSON.stringify(grouped.category3, null, 4))
Note that this json has 4 objects in result array, 2 of cat1, and 1 of cat 2 and cat3. You can run this code in a separate file to see how it works. Ofcourse you will be fetching the json object from server. I just set it for demonstration.
Then set teh state:
this.setState({ grouped })
Then in render() you only show the categories that have items like:
const menuBarButtons = Object.keys(this.state.grouped).map((category) => {
/* your jsx here */
return <MenuItem text={category} key={category} onClick={this.onClick} blah={blah}/>
/* or something , it's up to you */
})
I'm assuming you're showing the items based on the currently selected category this.state.selected. So after you have rendered your menu, you would do something like:
const selectedCatItems = this.state.grouped[this.state.selected].map((item) => {
return <YourItem name={item.name} key={item.id} blah={blah} />
})
Then render it:
return (
<div className="app">
<MenuBar blah={blah}>
{menuBarButtons}
</Menubar>
<div for your item showing area>
{selectedCatItems}
</div>
</div>
)
Also, don't forget to change your onClick() so that it sets this.state.selected state properly. I believe you can figure that out yourself.
Hope it helps.
PS: I didn't write a whole copy/paste solution to your problem simply because I'm reluctant to read and understand your UI details and the whole component to component data passing details..
I made a component containing two dropdown lists. The options in the second dropdown menu is supposed to be filtered depending on the selected option from the first dropdown menu.
Now, I want to map a filtered array that is stored in a const similary to the way i map options1:
render() {
const options1 = [
{value: 'one', label: 'One'},
{value: 'two', label: 'Two'}
];
const options2 = [
{value: 'one-a', label: 'One A', link: 'one'},
{value: 'one-b', label: 'One B', link: 'one'},
{value: 'two-a', label: 'Two A', link: 'two'},
{value: 'two-b', label: 'Two B', link: 'two'}
];
const filteredOptions = options2.filter(o => o.link === this.state.selectedOption.value);
return (
<div style={style}>
<div>
<label>Select one</label>
<select
value={this.state.selectedOption.value}
onChange={this.handleChange1}
>
{options1.map(tag => <option>{tag.value}</option>)}
</select>
</div>
<div>
<label>Then the other</label>
<select
value={this.state.selectedOption2.value}
onChange={this.handleChange2}
>
{filteredOptions.map(tag => <option>{tag.value}</option>)}
</select>
</div>
</div>
)
}
The first mapping of options1 works just fine. However, my select tag gets rendered empty for the mapping of filteredOptions.
I have no idea why it won't work. Anyone happen to have an idea?
Full code: https://www.codepile.net/pile/evNqergA
Here is a working example for what you're trying to do.
import React, { Component } from "react";
const options1 = [
{ value: "one", label: "One" },
{ value: "two", label: "Two" }
];
const options2 = [
{ value: "one-a", label: "One A", link: "one" },
{ value: "one-b", label: "One B", link: "one" },
{ value: "two-a", label: "Two A", link: "two" },
{ value: "two-b", label: "Two B", link: "two" }
];
export default class SelectsComponent extends Component {
handleChange1 = e => {
console.log(e);
this.setState({
selectedOption: { value: e.target.value }
});
};
handleChange2 = e => {
this.setState({
selectedOption2: { value: e.target.value }
});
};
constructor(props) {
super(props);
this.state = {
selectedOption: { value: "one" },
selectedOption2: { value: "one-a" }
};
}
render() {
const filteredOptions = options2.filter(
o => o.link === this.state.selectedOption.value
);
return (
<div>
<div>
<label>Select one</label>
<select
value={this.state.selectedOption.value}
onChange={this.handleChange1}
>
{options1.map(tag => (
<option>{tag.value}</option>
))}
</select>
</div>
<div>
<label>Then the other</label>
<select
value={this.state.selectedOption2.value}
onChange={this.handleChange2}
>
{filteredOptions.map(tag => (
<option>{tag.value}</option>
))}
</select>
</div>
</div>
);
}
}
In your scenario filteredOptions would be an empty Array.
The check for o.link === this.state.selectedOption.value is doing something wrong.
Check the value of this.state.selectedOption.value, this is not set correctly.
The best way to do this wouldn't be inside of the render method.
1) move your arrays into state or other instance members
2) make sure to only trigger the sorting once
this.setState(lastState => ({
...lastState,
options2: lastState.options2.filter(yourFilterFn)
}))
3) map the filtered array into JSX inside of your render method
Side-note: this uses immutable setState (which I gather is important given you create a new filtered array from the options2 in your example). If you want to follow an even more functional pattern, you can do the filtering inside of your render method (although I don't recommend it). If you decided to filter inside of your render method, consider using a memoization technique from React 16.7 (which is currently in Alpha).