isActive style in react-router v.6 - react-router

Could you please help me to understand why active style is all the time active? I've got "react-router-dom": "^6.1.1". I tried different variety of way to apply this stylies the way it's written in react router documentation, but still i can't find the mistake why it is so.
import { NavLink } from "react-router-dom";
import s from "../Sidebar/Sidebar.module.css";
function Sidebar() {
return (
<div className={s.Sidebar}>
<NavLink
to="/profile"
style={(isActive) => ({ color: isActive ? "green" : "blue" })}
className={s.navItems}
>
Profile
</NavLink>
<NavLink
to="/messages"
style={(isActive) => ({ color: isActive ? "green" : "blue" })}
className={s.navItems}
>
Messages
</NavLink>
<br />
</div>
);
}
export default Sidebar;
.navItems{
display: flex;
text-decoration: none;
font-size: 26px;
padding-bottom: 8px;
}
[1]: https://i.stack.imgur.com/cCsBw.png

In react-router-dom v6 the isActive is a prop value destructured from a function passed to either of the children, className, and style NavLink props.
NavLink
interface NavLinkProps
extends Omit<
LinkProps,
"className" | "style" | "children"
> {
caseSensitive?: boolean;
children?:
| React.ReactNode
| ((props: { isActive: boolean }) => React.ReactNode);
className?:
| string
| ((props: { isActive: boolean }) => string);
end?: boolean;
style?:
| React.CSSProperties
| ((props: {
isActive: boolean;
}) => React.CSSProperties);
}
Destructure isActive in your style callback, style={({ isActive }) => ({ color: isActive ? "green" : "blue" })}.
<NavLink
to="/profile"
style={({ isActive }) => ({ color: isActive ? "green" : "blue" })}
className={s.navItems}
>
Profile
</NavLink>

this is worked for me
const match = useMatch(`${path}/*`);
Usage example:
interface NavbarItemProps {
path: string;
title: string;
icon: OverridableComponent<SvgIconTypeMap> & { muiName: string };
variant: GLOBAL.GlobalSlice['leftDrawerVariant'];
}
const NavbarItem = ({ path, icon: Icon, title, variant }: NavbarItemProps): ReactElement => {
const match = useMatch(`${path}/*`);
return (
<LightTooltip
disableHoverListener={variant === 'large'}
placement="right"
title={title}
>
<ListItemButton
key={path}
className={classNames({ 'bg-white text-brand fill-brand': match })}
component={NavLink}
to={path}
>
<ListItemText
className="whitespace-nowrap overflow-hidden"
primary={title}
/>
</ListItemButton>
</LightTooltip>
);
};

Related

How i can do my component in React.js have a individual behavior?

I'm implementing a Like and Dislike Button, and I wanna that when I click them will be with other colors, but just the clicked component, when I click all buttons change the state, can anybody help me?
`
const indexPost = async () => {
const data = await api.get('/api/posts')
if(data.data.length !=0){
const dataArray = data.data
if(dataArray.length === 0) {
return
}else{
return(
setPost(dataArray.map( data => (
<Post key={data._id} id={data._id} title={data.title} text={data.text}>
<Like id={data._id}></Like>
</Post>
)))
)
}
}
}
export default function Like({itemId}) {
const context = useContext(notificationContext)
const {isLoved, Like, Loved, Unlike, isLike, isUnlike, setIsLike, setIsUnlike, setIsLoved } = context
return(
<div className={styles.likeContainer} key={itemId}>
{isLike ? (
<button className={styles.likeContent} onClick={() => setIsLike(false)}><Icon.ThumbsUp className={styles.Icon} fill="#5CB0BB" ></Icon.ThumbsUp></button>) :
(<button className={styles.likeContent} onClick={() => Like() }><Icon.ThumbsUp className={styles.Icon} ></Icon.ThumbsUp></button>)}
{isLoved ?
(<button className={styles.likeContent} onClick={() => setIsLoved(false)}><Icon.Heart className={styles.Icon} fill="red" ></Icon.Heart> </button>) :
(<button className={styles.likeContent} onClick={() => Loved() }><Icon.Heart className={styles.Icon} ></Icon.Heart></button>)}
{isUnlike ? (
<button className={styles.likeContent} onClick={() => setIsUnlike(false)}><Icon.ThumbsDown className={styles.Icon} fill="#702BA6" ></Icon.ThumbsDown> </button>) :
(<button className={styles.likeContent} onClick={() => Unlike()}><Icon.ThumbsDown className={styles.Icon} ></Icon.ThumbsDown></button>
)}
</div>
)
};
I have implemented the similar one in my project, it is very basic , it shows how to update the likes , you need to handle the cases of user authentication and stuff
App.js
import { useState, useEffect, createContext, useReducer } from "react";
import { updateArrayOfObj } from "./utils";
import AllPosts from "./AllPosts";
export const PostsContext = createContext();
const initialState = {
posts: [
{
_id: "1",
name: "Browny",
image: "http://placekitten.com/200/310",
likes: 0,
love: 0,
dislikes: 0
},
{
_id: "2",
name: "Blacky",
image: "http://placekitten.com/200/320",
likes: 0,
love: 0,
dislikes: 0
},
{
_id: "3",
name: "SnowWhite",
image: "http://placekitten.com/200/300",
likes: 0,
love: 0,
dislikes: 0
}
]
};
const reducer = (state, action) => {
switch (action.type) {
case "UPDATE_POST":
return {
...state,
posts: updateArrayOfObj(
state.posts,
action.payload.obj,
"_id",
action.payload._id
)
};
case "CREATE_POST":
return {
...state,
posts: [...state.posts, ...action.payload.data]
};
case "DELETE_POST":
return {
...state,
posts: state.posts.filter((ele) => ele._id !== action.payload._id)
};
default:
return state;
}
};
export default function App() {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<PostsContext.Provider
value={{
state,
dispatch
}}
>
<div className="App">
<AllPosts />
</div>
</PostsContext.Provider>
);
}
PostsAll.js
import Post from "./Post";
import { PostsContext } from "./App";
import { useContext } from "react";
export default function AllPosts() {
const { state } = useContext(PostsContext);
return (
<div className="allPosts">
{state.posts.map((item) => {
return (
<Post
name={item.name}
image={item.image}
likes={item.likes}
love={item.love}
dislikes={item.dislikes}
id={item._id}
key={item._id}
/>
);
})}
</div>
);
}
Post.js
import { PostsContext } from "./App";
import { useContext } from "react";
export default function Post(props) {
const { state, dispatch } = useContext(PostsContext);
const handleUserInteraction = (type, id) => {
dispatch({
type: "UPDATE_POST",
payload: {
obj: { [type]: props[type] + 1 },
_id: id
}
});
};
return (
<div className="post">
<h3>{props.name}</h3>
<img src={props.image} alt="cat" />
<br />
<button onClick={() => handleUserInteraction("likes", props.id)}>
{props.likes} Like
</button>{" "}
<button onClick={() => handleUserInteraction("love", props.id)}>
{props.love} Love
</button>{" "}
<button onClick={() => handleUserInteraction("dislikes", props.id)}>
{props.dislikes} Dislike
</button>
</div>
);
}
You can refer to this codesandbox to implement the same
You can use onClick() on each like button and attach it with a function, then you can get the value of that particular like with e.currentTarget.id and change its css/style the way you want.
const handleClick=(e)=>
{
console.log(e.currentTarget.id);
}

react native 2 dropdown depend on first one

I am trying to connect two dropdown with in react native,
same as country and city
if i select any country it should load cities from that country to second drop-down
all data is in a external json file
but nothing is loading in both drop down (picker)
json file :
{
"interest": [
{
"RAW_MATERIAL":["abc","cde"]
},
{
"OEM_PARTS":["xyz","qwer"]
},
{
"CONSUMABLES":["poiu","fjgl"]
},
{
"SERVICE":["xvcbv","qweiw"]
}
],
}
react native picker i use:
import React, { Component } from 'react';
import { Container,Picker,Button } from 'native-base';
const cData = require('../data.json');
export default class Vendorsupplies extends Component {
constructor(props) {
super(props);
this.state = {
interest:'',
interest2:''
};
}
interest(value: string) {
this.setState({
interest: value
});
}
interest2(value: string) {
this.setState({
interest2: value
});
}
<Picker
note
mode="dropdown"
style={{ width: 120 }}
selectedValue={this.state.interest}
onValueChange={this.interest.bind(this)}
name="intre"
>
{cData.interest.map((number) =>
<Picker.Item label={number.interest_in} value={number.interest_in} />
)}
</Picker>
<Picker
note
mode="dropdown"
style={{ width: 120 }}
selectedValue={this.state.intre2.interest}
onValueChange={this.intre2.interest.bind(this)}
name="intre2"
>
{cData.interest.map((number) =>
<Picker.Item label={number.intre2.interest_in} value={number.intre2.interest_in} />
)}
</Picker>
You can try it like that, I just done it with select but you will get the idea.
const cData = {
interest: [
{
RAW_MATERIAL: ['abc', 'cde'],
},
{
OEM_PARTS: ['xyz', 'qwer'],
},
{
CONSUMABLES: ['poiu', 'fjgl'],
},
{
SERVICE: ['xvcbv', 'qweiw'],
},
],
};
class TodoApp extends React.Component {
constructor(props) {
super(props);
this.state = {
interest: 'RAW_MATERIAL',
interest2: '',
};
}
renderOption() {
const el = cData.interest.find(
interest => Object.keys(interest)[0] === this.state.interest
);
if (el) {
return el[this.state.interest].map(option => (
<option value={option}>{option}</option>
));
}
return <option>empty</option>;
}
render() {
return (
<React.Fragment>
<select
value={this.state.interest}
onChange={e => {
e.persist();
this.setState(prev => ({
...prev,
interest: e.target.value,
}));
}}
>
{cData.interest.map(el => (
<option value={Object.keys(el)}>{Object.keys(el)}</option>
))}
</select>
<select
value={this.state.interest2}
onChange={e => {
e.persist();
this.setState(prev => ({ ...prev, interest2: e.target.value }));
}}
>
{this.renderOption()}
</select>
</React.Fragment>
);
}
}
ReactDOM.render(<TodoApp />, document.querySelector("#app"))
<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>
<div id="app"></div>

Render input fields dynamically inside a list

I have set of components where it would consist of input fields along with text rows.
As given in the image the users should be able to add categories and description. After adding them they will be rendered as a list of components. like this
Inside a category there will be tags as given in the above image and to add them i have to add a input component. This input component should be available only when the user clicks on the Add tag button below each category row. When a user clicks on it,it should enable the input(should render a input component inside the selected category row) and should be able to type the tag name on it and save it. I need to make this input field enable only when i click on the add tag button. and it should enable only in the selected category row. This is the code that i have tried.
import React, { Component, Fragment } from "react";
import { Button, Header, Input } from "semantic-ui-react";
import "semantic-ui-css/semantic.min.css";
import ReactDOM from "react-dom";
class App extends Component {
state = {
category: "",
description: "",
categories: []
};
onChange = (e, { name, value }) => {
this.setState({ [name]: value });
};
addCategory = () => {
let { category, description } = this.state;
this.setState(prevState => ({
categories: [
...prevState.categories,
{
id: Math.random(),
title: category,
description: description,
tags: []
}
]
}));
};
addTag = id => {
let { tag, categories } = this.state;
let category = categories.find(cat => cat.id === id);
let index = categories.findIndex(cat => cat.id === id);
category.tags = [...category.tags, { name: tag }];
this.setState({
categories: [
...categories.slice(0, index),
category,
...categories.slice(++index)
]
});
};
onKeyDown = e => {
if (e.key === "Enter" && !e.shiftKey) {
console.log(e.target.value);
}
};
tags = tags => {
if (tags && tags.length > 0) {
return tags.map((tag, i) => {
return <Header key={i}>{tag.name}</Header>;
});
}
};
enableTagIn = id => {};
categories = () => {
let { categories } = this.state;
return categories.map(cat => {
return (
<Fragment key={cat.id}>
<Header>
<p>
{cat.title}
<br />
{cat.description}
</p>
</Header>
<Input
name="tag"
onKeyDown={e => {
this.onKeyDown(e);
}}
onChange={this.onChange}
/>
<Button
onClick={e => {
this.addTag(cat.id);
}}
>
Add
</Button>
{this.tags(cat.tags)}
</Fragment>
);
});
};
render() {
return (
<Fragment>
{this.categories()}
<div>
<Input name="category" onChange={this.onChange} />
<Input name="description" onChange={this.onChange} />
<Button onClick={this.addCategory}>Save</Button>
</div>
</Fragment>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
This is the codesandbox url.
Any idea on how to achieve this?.
I changed your code by using function components and react hooks and i created category component which has it own state like this:
import React, { Fragment } from "react";
import { Button, Header, Input } from "semantic-ui-react";
import "semantic-ui-css/semantic.min.css";
import ReactDOM from "react-dom";
const App = () => {
const [Category, setCategory] = React.useState({
title: "",
description: ""
});
const [Categories, setCategories] = React.useState([]);
return (
<div>
{console.log(Categories)}
<Input
value={Category.title}
onChange={e => setCategory({ ...Category, title: e.target.value })}
/>
<Input
value={Category.description}
onChange={e =>
setCategory({ ...Category, description: e.target.value })
}
/>
<Button onClick={() => setCategories([...Categories, Category])}>
Save
</Button>
<div>
{Categories.length > 0
? Categories.map(cat => <CategoryItem cat={cat} />)
: null}
</div>
</div>
);
};
const CategoryItem = ({ cat }) => {
const [value, setvalue] = React.useState("");
const [tag, addtag] = React.useState([]);
const [clicked, setclicked] = React.useState(false);
const add = () => {
setclicked(false);
addtag([...tag, value]);
};
return (
<Fragment>
<Header>
<p>
{cat.title}
<br />
{cat.description}
</p>
</Header>
<Input
name="tag"
value={value}
style={{ display: clicked ? "initial" : "none" }}
onChange={e => setvalue(e.target.value)}
/>
<Button onClick={() => (clicked ? add() : setclicked(true))}>Add</Button>
<div>{tag.length > 0 ? tag.map(tagname => <p>{tagname}</p>) : null}</div>
</Fragment>
);
};
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
and here a sandbox

Open and close expandable button in list view

I have a list of Messages that you should be able to click and expand more for info. At the moment, my implementation expands/collapses all messages by clicking on any message.
I tried using the code below:
this.state = {
activeIndex:0,
isExpandable:false
}
And applying the condition as:
{!this.state.isExpandable && this.state.activeItem === i} to the map() where i was retrieving properties of each object.
image of buttons in collapsable state
image of buttons in expanded state
import React, { Component } from 'react'
import { Card, Feed } from 'semantic-ui-react'
import { Input } from 'react-input-component';
import { Collapse, Button} from 'reactstrap';
import styled from 'styled-components';
function searchingForName(search){
return function(x){
return x.firstName.toLowerCase().includes(search.toLowerCase()) || x.lastName.toLowerCase().includes(search.toLowerCase()) || !search ;
}
}
class Home extends Component {
constructor(props){
super(props);
this.state = {
results:[],
search:'',
collapse:false,
newSearch:'',
tags:[],
isExpandable:false,
activeIndex:0
}
this.onchange = this.onchange.bind(this);
this.toggle = this.toggle.bind(this);
this.inputKeyDown = this.inputKeyDown.bind(this);
// this.handleKeyPress = this.handleKeyPress.bind(this);
}
onchange = e => {
console.log(this.state.search)
this.setState({search:e.target.value});
}
// handleKeyPress = e => {
// if(e.key === 'Enter'){
// this.setState({newSearch: e.target.value});
// }
// }
inputKeyDown = (e) => {
const val = e.target.value;
if(e.key === 'Enter' && val){
if (this.state.tags.find(tag => tag.toLowerCase() === val.toLowerCase())) {
return;
}
this.setState({tags: [...this.state.tags,val]});
this.tagInput.value=null;
}
}
toggle(){
this.setState({collapse: !this.state.collapse});
}
componentDidMount(){
fetch('https://www.hatchways.io/api/assessment/students')
.then(res => res.json())
.then(data => {
console.log(data.students);
this.setState({results:data.students})
}).catch(err => {
console.log(err);
});
}
render() {
return (
<div>
<Card style={{'marginTop':'40px','width':'520px','marginRight':'auto','marginLeft':'auto'}}>
<Card.Content>
<Input
style={{'width':'519px'}}
placeholder="Search by name..."
onChange={this.onchange}
/>
<Input
style={{'width':'519px'}}
placeholder="Search by tags..."
onChange={this.onchange}
/>
{this.state.results.length ?
this.state.results.filter(searchingForName(this.state.search)).map((value,i) => (
<Feed>
<Feed.Event style={{'margin':'10px'}}>
<Image>
<Feed.Label image={value.pic} />
</Image>
<div style={{'float':'right'}}>
{!this.state.collapse ?
<Button onClick={this.toggle}>+</Button>
: <Button onClick={this.toggle}>-</Button>}
</div>
<Feed.Content style={{'textAlign':'center','marginBottom':'10px'}}>
<Feed.Summary><strong>{value.firstName.toUpperCase()} {value.lastName.toUpperCase()}</strong></Feed.Summary>
<Feed.Summary>Email: {value.email}</Feed.Summary>
<Feed.Summary>Company: {value.company}</Feed.Summary>
<Feed.Summary>Skill: {value.skill}</Feed.Summary>
<Feed.Summary>Average : {value.grades.map((x,i,arr)=> {
return x/arr.length;})
.reduce((a,b) => {
return a + b;
}) + "%"}
</Feed.Summary><br />
<Collapse isOpen={this.state.collapse}>
<Feed.Summary>
{Array.isArray(value.grades) && value.grades.map(val => {
return <div>Test {value.grades.indexOf(val)} : {parseFloat(val) + "%"}</div>
})}
</Feed.Summary><br />
{this.state.tags.map((tag,index) => (
<div>
<span className="addTag"key={index}>{tag}</span>
</div>
))}<br />
<input
type="text"
onKeyDown={this.inputKeyDown}
ref={c => { this.tagInput = c; }}
placeholder="add a tag..."
/>
{/* <div>{this.state.newSearch}</div><br />
<Input
style={{'width':'200px'}}
placeholder="add a tag..."
value={this.state.newSearch}
onKeyPress={this.handleKeyPress}
/> */}
</Collapse>
<hr/>
</Feed.Content>
</Feed.Event>
</Feed>
)) : ''}
</Card.Content>
</Card>
</div>
)
}
}
const Image = styled.div`
border: 1px solid #001;
border-radius: 60px;
overflow:hidden;
padding:18px;
height:90px;
width: 90px;
margin-top:30px;
margin-right:auto;
margin-left:auto;
margin-bottom:20px;
`
export default Home;
What is causing them all to expand/collapse at once and how can i change that to only expand/collapse the button is clicked?
Your main problem is that you don't have isOpened card for every student. You can only open all or none with one single collapse state. I have updated your code with solution here:
https://codesandbox.io/s/peaceful-kapitsa-tr9yn
I have changes toggle function, which takes index as parameter and updates single students card status - isOpened true or false.
toggle(index) {
const results = this.state.results.map((item, idx) => {
if (index === idx) {
return {
...item,
isOpened: !item.isOpened
};
}
return item;
});
this.setState({ results });
}
When you load all students data from API endpoint, you have to map through all items and add default isOpened state (by default I've added false - closed).
componentDidMount() {
fetch("https://www.hatchways.io/api/assessment/students")
.then(res => res.json())
.then(data => {
console.log(data.students);
const results = data.students.map(student => {
return {
...student,
isOpened: false
};
});
this.setState({ results });
})
.catch(err => {
console.log(err);
});
}
In render() method I have updated every item to check not this.state.collapse, but student.isOpened on Collapse component and toggle button.
Toggle button
<div style={{ float: "right" }}>
{!value.isOpened ? (
<Button onClick={() => this.toggle(i)}>+</Button>
) : (
<Button onClick={() => this.toggle(i)}>-</Button>
)}
</div>
Collapse component
<Collapse isOpen={value.isOpened}>
...
</Collapse>

Can't update props of child components generated from JSON

I just started learing react and I run in a trouble trying to update state of a single <Option /> child Element.
My flux Store is emiting change and in React devtools I can see the state of StyleOptions element being updated but it doesn't update the child components <Option />.
I suspect this is because I got the list of options kept in a variable.
I need to use this because I'm pulling this options from JSON.
const Options = this.state.options.map((parent) => {
const children = parent.children.map((child) => {
return (
<Option {...child} />
)
});
return <Option {...parent} children={children} />;
});
So I think this part might be causing problems.
My example data from OptionsStore looks like this.
this.options = [
{
key: "suitType",
label: "Suit Type",
selected: false,
children: [
{
key: "suittype_skinny",
parent: "suitType",
label: "Skinny",
price: "£50",
description: "Short description",
images: {
general: "http://placehold.it/600x600",
closeUp: "http://placehold.it/620x620",
thumbnail: "http://placehold.it/100x100",
},
selected: false,
},
{
key: "suittype_wedding",
parent: "suitType",
label: "Wedding",
price: "£50",
description: "Short description",
images: {
general: "http://placehold.it/600x600",
closeUp: "http://placehold.it/620x620",
thumbnail: "http://placehold.it/100x100",
},
selected: false,
}
]
}
]
Also the child props aren't being changed.
Full code here:
import React, { Component } from 'react';
import Option from './Option';
import OptionsStore from '../../stores/OptionsStore';
class StyleOptions extends Component {
constructor(props) {
super(props)
this.state = {
options: OptionsStore.getAllItems(),
}
}
componentDidMount() {
OptionsStore.on('change',(e) => {
this.setState({
options: OptionsStore.getAllItems(),
});
console.log('optionsStore received an update');
});
}
render() {
const Options = this.state.options.map((parent) => {
const children = parent.children.map((child) => {
return (
<Option {...child} />
)
});
return <Option {...parent} children={children} />;
});
return(
<div className="col-xs-6">
<ul className="list-group">
{Options}
</ul>
</div>
)
}
}
export default StyleOptions;
also the <Option /> code:
import React, { Component } from 'react';
export default class Option extends Component {
constructor(props) {
super(props);
this.hasChildren = this.props.children ? true : false;
this.hasThumb = this.props.images ? true : false;
this.children = this.state.children;
this.state = {
label: this.props.label,
description: this.props.description,
selected: false,
price: this.props.price
}
}
render() {
return (
<li className={this.hasChildren ? 'list-group-item':'col-sm-4 list-group-item' } selected={this.state.selected}>
<a className="media">
{this.hasThumb ? (
<div className="media-left media-middle">
<img src={this.props.images.thumbnail} alt={this.state.label} />
</div>
) : (
' '
)}
<div className="media-body">
<h4 className="option-name">{this.state.label}</h4>
<p className="info">{this.state.description}</p>
<span className="text-success pricing">{this.state.price}</span>
</div>
</a>
{this.hasChildren ? (
<ul className="panel-body">
{this.children}
</ul>
) : (
' '
)}
</li>
)
}
}
I hope anyone could help.
The issue is inside of your Option component.
You define this.children = this.state.children . After that, you define your initial state but there is no "children". So that children state is notdefined.
First, add children: this.props.children into your state.
Then, change
{this.hasChildren ? (
<ul className="panel-body">
{this.children}
</ul>
) : (
' '
)}
to
{this.hasChildren ? (
<ul className="panel-body">
{this.state.children}
</ul>
) : (
' '
)}
and there is no need to define this.children = this.state.children.
I hope it solves the issue.
Thank you alireza for your help.
I managed to fix it. The problem was that the <Option /> was receiving too much info. I removed all state calls and left only the if statements like below.
import React, { Component } from 'react';
export default class Option extends Component {
constructor(props) {
super(props);
this.hasChildren = this.props.children ? true : false;
this.hasThumb = this.props.images ? true : false;
//this.state = this.props;
}
render() {
return (
<li className={this.hasChildren ? 'list-group-item':'col-sm-4 list-group-item' }>
<a className="media">
{this.hasThumb ? (
<div className="media-left media-middle">
<img src={this.props.images.thumbnail} alt={this.props.label} />
</div>
) : (
' '
)}
<div className="media-body">
<h4 className="option-name">{this.props.label}</h4>
<p className="info">{this.props.description}</p>
<span className="text-success pricing">{this.props.price}</span>
</div>
</a>
{this.hasChildren ? (
<ul className="panel-body">
{this.props.children}
</ul>
) : (
' '
)}
</li>
)
}
}
Then modified my stateful component <StyleOptions /> like below
import React, { Component } from 'react';
import Option from './Option';
import OptionsStore from '../../stores/OptionsStore';
class StyleOptions extends Component {
constructor(props) {
super(props)
this.state = {
options: OptionsStore.getAllItems(),
}
}
componentWillMount() {
OptionsStore.on("change", () => {
this.setState({
options: OptionsStore.getAllItems(),
});
console.log('optionsStore received an update');
});
}
render() {
const { options } = this.state;
const allOptions = options.map((option) => {
const { children } = option;
const optionChildren = children.map((child) => {
return <Option {...child} />;
})
return <Option {...option} children={optionChildren} />;
});
return(
<div className="col-xs-12">
<ul className="list-group">
{allOptions}
</ul>
</div>
)
}
}
export default StyleOptions;
Not sure why it is working correctly now. I suspect that It might have changed because I modified the maps a little bit.
Old one / Broken one:
const Options = this.state.options.map((parent) => {
const children = parent.children.map((child) => {
return (
<Option {...child} />
)
});
return <Option {...parent} children={children} />;
});
New one/working:
const { options } = this.state;
const allOptions = options.map((option) => {
const { children } = option;
const optionChildren = children.map((child) => {
return <Option {...child} />;
})
return <Option {...option} children={optionChildren} />;
});