I want to create an array with some elements and then iterate (with .forEach or .map) it.
but each of array elements must have different style. for example I have an array like that:
["johnny red", "Stephanie blue", "Hans green", "Fifty Shades Of grey :d"]
also, I want reuse some of array's individual elements in another component.
how can i do that?
(imagine that last word in each element is a individual style e.g. background-color or color,)
Can you help me?
please give me an advice, what would I do?
There are many ways to achieve this, the key difference is how you are representing your value-style pairs.
Eventually, you need to map the values to their styles.
For example:
const myStyles = {
'johnny red': { color: 'red' },
'Stephanie blue': { color: 'blue' },
'Hans green': { color: 'green' },
'Fifty Shades Of grey :d': { color: 'pink' }
};
export default function App() {
return (
<FlexBox>
<FlexItem>
{Object.entries(myStyles).map(([key, style]) => (
<div key={key} style={style}>
{key}
</div>
))}
</FlexItem>
</FlexBox>
);
}
It's not very clear what you want, but you can attach styles to components like this:
const values = [
{
text: "one",
css: { color: 'blue' }
},
{
text: "two",
css: { color: 'red' }
},
];
const Test = props => {
const { values } = props;
return (
<div>{values.map(
(value, i) => <div key={i} style={value.css}>{value.text}</div>
)}</div>
);
}
ReactDOM.render(
<Test values={values} />,
document.getElementById("react")
);
<div id="react"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
You mean something like this? The snippet is below and here is the codepen texample: https://codepen.io/tormod17/pen/apvXoW?editors=0010
Also, have you considered incorporating styled components with react? It could help with this project. https://www.styled-components.com/docs/basics
{children.map(element => {
return (
<element.type
{...element.props}
style={{
height: '33%',
}}
/>
)
})}
This is from another project:
import * as React from "react";
import { IAddressListProps } from '../../detailPage/components/interfaces/IAddressListProps';
import { config } from "../../config";
export class PrintAddressList extends React.Component<IAddressListProps, {}>{
constructor(props: IAddressListProps) {
super(props);
}
private createAddressCard = () => {
let parent = [];
this.props.items.map((address) => {
parent.push(<div style={{ padding: '10px', border: '1px solid #ccc', margin: '5px' }}>
<label>{config.colNames.addressList.clmnAddressType}: </label>
<label>{address.Adressart}</label><br />
<label>{config.colNames.addressList.clmnCompanyName}: </label>
<label>{address.Firma}</label><br />
<label>{config.colNames.addressList.clmnPlaceName}: </label>
<label>{address.Ort}</label><br />
<label>{config.colNames.addressList.clmnZipCode}: </label>
<label>{address.PLZ}</label><br />
<label>{config.colNames.addressList.clmnTelephone}: </label>
<label>{address.Telefon}</label><br />
</div>);
});
return parent;
}
public render(): React.ReactElement<IAddressListProps> {
return (
<div>
{this.createAddressCard()}
</div>
);
}
}
Related
I'm new to StackOverflow and looking forward to contributing back to the community!
My first question, I am trying to make some squares change color on the screeen, after an onClick event. I'm nearly there, but I keep getting an error when I try to update the state, which then should updates the color. Please could you let me know what I'm doing wrong?
App.js
import React from "react"
import boxes from "./boxes"
import Box from "./Box"
export default function App() {
const [squares, setSquares] = React.useState(boxes)
function changeOn() {
console.log(squares)//just checking I'm getting the full object
setSquares({
id: 1, on: false //this was previously [...prev], on: !squares.on
})
}
const squaresElement = squares.map(props => (
<Box key={props.id} on={props.on} onClick={changeOn} />
))
return (
<main>
{squaresElement}
</main>
)
}
Box.js
import React from "react"
export default function Box (props) {
const styles= props.on ? {backgroundColor: "#222222"} : {backgroundColor: "none"}
return (
<div className="box" style={styles} onClick={props.onClick}></div>
)
}
Boxes.js
export default [
{
id: 1,
on: true
},
{
id: 2,
on: false
},
{
id: 3,
on: true
},
{
id: 4,
on: true
},
{
id: 5,
on: false
},
{
id: 6,
on: false
},
]
I hope somebody can easily spot what's wrong here?
I was expecting to see the color of the top left box change to a different color, after a click.
There are two issues:
setSquares needs the whole array, so you need to give it a new squares array
The styling back to None does not work always. better to give it the white color again
Please find the codesandbox
export default function App() {
const [squares, setSquares] = React.useState(boxes);
function changeOn(id) {
setSquares(
squares.map((square) => {
return { ...square, on: id === square.id ? !square.on : square.on };
})
);
}
const squaresElement = squares.map((props) => (
<Box key={props.id} on={props.on} onClick={() => changeOn(props.id)} />
));
return <main>{squaresElement}</main>;
}
And in Box.js
const styles = props.on
? { backgroundColor: "#222222" }
: { backgroundColor: "#fff" };
You're calling setSquares and passing it a single object instead of an array.
On the next render squares.map(...) blows up because squares is the object, and the object doesn't have a map method.
// after this call squares is just this one object
setSquares({
id: 1, on: false
})
Here's a possible implementation that pushes the on/off responsibility into the box component itself.
// generates a list of items (faking your boxes.js)
const boxes = Array.from({length: 9}, (_, id) => ({ id }));
// container element to render the list
function Boxen ({ items }) {
return (
<div className="container">
{items.map((item, idx) => (
<Box item={item} key={idx} />
))}
</div>
)
}
// component for a single box that can toggle its own on/off state
function Box ({item}) {
const [active, setActive] = React.useState();
return (
<div onClick={() => setActive(!active)} className={active ? 'active' : ''}>{item.id}</div>
)
}
ReactDOM.render(<Boxen items={boxes}/>, document.getElementById('root'));
.container {
display: grid;
grid-template-columns: repeat(3, 100px);
grid-template-rows: repeat(3, 100px);
gap: 1em;
}
.container > * {
display: flex;
justify-content: center;
align-items: center;
background: skyblue;
}
.container > .active {
background: slateblue;
color: white;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.14.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.14.0/umd/react-dom.production.min.js"></script>
<div id="root"></div>
I successfully mapped JSON inventory data into a React Table. My goal is to use buttons to filter this table and render the table results based on the filter conditions. How do I do this?
Button Filters Component:
import React from 'react'
import Button from './Button'
const Form = ({reqType, setReqType, color, setColor, handleColorChange}) => {
return (
<form onSubmit={(e)=> e.preventDefault()}>
<Button
buttonText="Red"
>
</Button>
<Button
buttonText="White"
/>
</form>
)
}
export default Form
Table Component:
import React from 'react'
import Row from './Row'
const Table = ({ wines }) => {
return (
<table >
<tbody >
{wines.map((wine, key) =>(
<Row wine={wine} key={key}/>
))}
</tbody>
</table>
)
}
export default Table
Row Component:
import React from 'react'
import Cell from './Cell'
const Row = ({ wine }) => {
return (
<tr>
{Object.entries(wine).map(([key, value]) => {
return (
<Cell key={key} cellData={JSON.stringify(value)}/>
)
} ) }
</tr>
)
}
export default Row
Cell Component:
import React from 'react'
const Cell = ({cellData,wine}) => {
return (
<td >
{cellData}
</td>
)
}
export default Cell
App Component:
<Form
reqType={reqType}
setReqType={setReqType}
color={color}
setColor={setColor}
handleColorChange={handleColorChange}/>
<Table wines={wines}/>
I mentioned that you need a state for the filtered data. You don't. But you do need two - one to hold the full data set, and another to maintain the colour. You can then use a function to filter out objects based on their colour.
So I've played around with your code, removed a bunch of things to make this example readable, added a Button component, added a reset button, and added a basic dataset.
Hopefully you can see how it all fits together.
const { useState } = React;
// We passing in the data - you may not being doing this
// your list of wines may come from an API call, but I'm
// keeping this simple
function Example({ data }) {
// Set the wines state to the passed in data,
// and initialise the color state (to undefined)
const [ wines, setWines ] = useState(data);
const [ color, setColor ] = useState();
// Simple function to accept a color
// as an argument and update the state with it
function handleColor(color) {
setColor(color);
}
// If color is undefined return all the wines!
// Otherwise `filter` the wines based on their colour
function filterData(wines, color) {
if (!color) return wines;
return wines.filter(wine => wine.color === color);
}
// Pass down the handleColor function in the Form props,
// and call `filteredData` to have an updated list of wines
// that you pass as a props to the table
return (
<div>
<Form handleColor={handleColor} />
<Table wines={filterData(wines, color)} />
</div>
);
}
// Pass in the `handleColor` function
function Form({ handleColor }) {
// Buttons get their own `handleClick` function
// which extracts the colour from the button's dataset
// and then calls `handleColor` with that color
function handleClick(e) {
const { color } = e.target.dataset;
handleColor(color);
}
// Button components get text, color,
// and the `handleClick` function as props
return (
<div>
<Button
text="Red"
color="red"
handleClick={handleClick}
/>
<Button
text="White"
color="white"
handleClick={handleClick}
/>
<Button
text="Reset"
color=""
handleClick={handleClick}
/>
</div>
);
}
function Button({ text, color, handleClick }) {
return (
<button
data-color={color}
onClick={handleClick}
>{text}</button>
);
}
function Table({ wines }) {
return (
<table>
<tbody>
{wines.map(wine => (
<Row wine={wine} key={wine.id}/>
))}
</tbody>
</table>
);
}
function Row({ wine }) {
return (
<tr>
{Object.entries(wine).map(([key, value]) => {
return <Cell key={value} value={value} />;
})}
</tr>
)
}
function Cell({ value }) {
return <td>{value}</td>;
}
const data = [
{ id: 1, name: 'Plonk', color: 'red' },
{ id: 2, name: 'Rose', color: 'red' },
{ id: 3, name: 'Vanilla', color: 'white' },
{ id: 4, name: 'White', color: 'white' },
{ id: 5, name: 'Plonk', color: 'red' },
{ id: 6, name: 'Steve', color: 'white' }
];
ReactDOM.render(
<Example data={data} />,
document.getElementById('react')
);
button { margin-right: 0.2em; }
table { border-collapse: collapse; border: 1px solid #676767; margin-top: 1em; }
table td { padding: 0.4em; border: 1px solid #efefef; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="react"></div>
Given a component that renders its children, I can't get the children to render sorted as per their newOrder order:
export default class EnhancedLinks extends React.Component {
render() {
return (
<div>
{React.Children.map(
this.props.children.filter((c) => c),
(el) => el
)}
</div>
);
}
}
export default class App extends React.Component {
render() {
const newOrder = ["dandelion", "cantaloupe", "apple", "banana"];
return (
<div>
<EnhancedLinks>
<div name="apple" color="red">apple</div>
<div name="banana" color="yellow">banana</div>
<div name="cantaloupe" color="orange">cantaloupe</div>
<div name="dandelion" color="green">dandelion</div>
</EnhancedLinks>
</div>
);
}
}
Any idea how to get the EnhancedLinks children to render as per the order of the newOrder array?
Here's a fiddle:
https://codesandbox.io/s/react-and-scss-forked-z1p0b?file=/src/index.js
Map the newOrder array to <div>s instead of writing them out individually?
const colors = ['red', 'yellow', 'orange', 'green'];
return (
<div>
<EnhancedLinks>
{newOrder.map((name, i) => <div name={name} color={colors[i]}>{name}</div>)}
</EnhancedLinks>
</div>
);
The
Your EnchancedLinks component should render the div, color and text, not the outside wrapping component. This way there's less copy/pasted code and you can set the order in your array, or manipulate your array as you need to.
export default class EnhancedLinks extends React.Component {
render() {
return (
<div name={this.props.name} color={this.props.color}>
{this.props.name}
</div>
);
}
}
export default class App extends React.Component {
render() {
const newOrder = [
{
name: "dandelion",
color: "green"
},
{
name: "cantaloupe",
color: "orange"
},
{
name: "apple",
color: "red"
},
{
name: "banana",
color: "yellow"
}];
return (
<div>
{newOrder.map((link) => {
return <EnhancedLinks {...link} />
})}
</div>
);
}
}
I've forked your fiddle with a solution I've come up with: https://codesandbox.io/s/react-and-scss-forked-c1r1f
const Dropdown = ({ options, selected, onSelectedChange }) => {
const [ open, setopen ] = useState(false);
const renderedOptions = options.map((option) => {
if (option.value === selected.value) {
return null;
}
return (
<div key={option.value} className="item" onClick={() => onSelectedChange(option)}>
{option.label}
</div>
);
});
return (
<div className="ui form">
<div className="field">
<label className="label">Select a color</label>
<div onClick={() => setopen(!open)} className={`ui selection dropdown ${open ? 'visible active' : ''}`}>
<i className="dropdown icon" />
<div className="text">{selected.label}</div>
<div className={`menu ${open ? 'visible transition' : ''}`}>{renderedOptions}</div>
</div>
</div>
//Here is the selected.value state (value contains string of color name
{<div style={{ color: `${selected.value}` }}>{selected.value}</div>}
</div>
);
};
export default Dropdown;
const options = [
{
label: 'The Color Red',
value: 'red'
},
{
label: 'The Color Green',
value: 'green'
},
{
label: 'The Color Blue',
value: 'blue'
}
];
How can I use the selected.value in an external CSS file?
The data in the selected.value is a string of color name(s).
You can probably use Styled Components if that's what you're looking for, just an example, not really well thought out. The component can be in another file
const HoveredLink = styled.span`
color: ${props => props.selected ? 'black' : 'rgb(150, 153, 156)'};
`
<HoveredLink selected={\\someconditionhere} > Hover me <HoveredLink/>
You can simple use as a variable, this is not exactly CSS. So this one should work:
<div style={{color: selected.value}} >{ selected.label } </div>
You can also set style as a new variable:
const Dropdown = ({options,...}) => {
const styleDiv = {
color: options.value
}
//...
return (
//...
<div style={styleDiv}> {options.label} </div>
)
}
Here is how I solved it by using concept from this URL
import styles from './colorchange.css';
//...
//For setting default value (and closing dropdown when clicked outside)
useEffect(() => {
document.body.addEventListener('click', (event) => {
if (ref.current.contains(event.target)) {
return;
}
setopen(false);
});
document.documentElement.style.setProperty(`--variablename`, selected.value);
}, []);
//...
//inside renderedoption
return (
<div
key={option.value}
className="item"
onClick={() => {
onSelectedChange(option);
document.documentElement.style.setProperty(`--variablename`, option.value);
}}
>
{option.label}
</div>
);
//....
//for printing the color
<div className="colorcolor">This text is: {selected.value}</div>
CSS FILE:
{
--variablename: default;
}
.colorcolor {
color: var(--variablename);
}
Another way using CSS stylesheet.
Usually when I need to pass a value to use it for CSS I'll
go for specific CSS classes as I rather use the stylesheet
for style ( !== style within component ) for scalability reasons &
ease to access. If it can help ...
I. Known values case / no need to convert into word
to expect ( seems like it should be either [ blue,red,green ])
<div className = { selected.value } />
II. Need to convert into word
Let's say you need to change a selected.value that could be an hexadecimal value, you'll need to associate a word className you could use for CSS later on.
This is just an example and you can do a lot more within the expression passed
// convert anticipated value to the word you need
const colors = {'#F00': 'red', '#0F0' : green, '#00F': 'blue'};
<div className = { colors[ selected.value ] } />
📌Applied example
import './style.css' // style.css as same level of your component
const Dropdown = ({options,...}) => {
// if need to make wording *(cf:. case )
// const color = {'#F00': 'red', '#0F0' : green, '#00F': 'blue'};
//...
return (
//...
// if need to make wording *(cf:. case )
// <div className = { colors[ selected.value ] }> { selected.value } </div> */ }
<div className = { selected.value }> { selected.value } </div>
)
}
CSS for the above cases.
/*CSS file: style.css*/
.red { ...code... }
.green { ...code... }
.blue { ...code... }
I am trying to set inline styles in my React application. In this case, for a span:
<span className="myClass" style={{float : 'left', paddingRight : '5px'}} > </span>
React tells me:
Uncaught Invariant Violation: The style prop expects a mapping from
style properties to values, not a string. For example,
style={{marginRight: spacing + 'em'}} when using JSX. This DOM node
was rendered by `SentenceView
I am not quite sure what it means.
PS: I have tried different versions, so I did paddingRight: 5 as well as paddingRight: 5 + 'px' as well as paddingRight : 5px, but I didn't have any success!
Use "styles" prop instead of style
<span className="myClass" style={{float : 'left', paddingRight : '5px'}} > </span>
Here is a great reference from W3Schools which also shows you how to create an object with styling information, and refer to it in the style attribute:
reference for how to style React using CSS
There some ways to set style for React Components.
https://facebook.github.io/react/docs/context.html
https://github.com/facebookincubator/create-react-app
using style={css_object} or style={{color: this.props.color}}
using className="your-class-name"
React REPL
https://jscomplete.com/repl
1 style Object
// <span style={styles}>
const styles = {
color: "red",
background: "#0f0",
fontSize: "32px"
};
const BTN = (props) => {
return (
<div>
My name is <button>{props.name}</button>
<hr/>
I'm <span style={styles}>{props.age}</span> yeas old!
</div>
);
};
const infos = {
name: "xgqfrms",
age: 23
};
ReactDOM.render(<BTN {...infos} />, mountNode);
// <span style={{color: styles.color}}>
const styles = {
color: "red",
background: "#0f0",
fontSize: "32px"
};
const BTN = (props) => {
return (
<div>
My name is <button>{props.name}</button>
<hr/>
I'm <span style={{color: styles.color}}>{props.age}</span> yeas old!
</div>
);
};
const infos = {
name: "xgqfrms",
age: 23
};
ReactDOM.render(<BTN {...infos} />, mountNode);
2 className & stylesheet.css
import './styles.css';
/*
.classname-color{
color: "red";
background: "#0f0";
}
*/
const BTN = (props) => {
return (
<div>
My name is <button>{props.name}</button>
<hr/>
I'm <span className="classname-color">{props.age}</span> yeas old!
</div>
);
};
const infos = {
name: "xgqfrms",
age: 23
};
ReactDOM.render(<BTN {...infos} />, mountNode);
.classname-color{
color: "red";
background: "#0f0";
}
JSX and HTML are different. See the graphic below from Udemy:
In HTML it is
<div style="background-color: red;"></div>
In JSX you write
<div style={{ backgroundColor: 'red' }}></div>
Conditional inline formatting are different in both.
This is the way how you can define and use inline style with react.
/**
* Style definitions.
*/
const STYLE = {
infoColor: {
color: 'green'
},
warningColor: {
color: 'orange'
},
errorColor: {
color: 'red'
}
};
/**
* Component
*/
class Welcome extends React.Component {
/**
* Rendering into the DOM.
*/
render() {
return (
<div>
<h2 style={STYLE.infoColor}>Welcome!</h2>
)
}
}
when we use inline styling in react we should always use style={{styleproperties}}
Error:
<input style="margin:0 15px 0 0"/>
Solution:
<input style={{margin:"0 15px 0 0"}}/>
don't wrap the {{}} in double quotes or string