Reputation: 363
I recently started learning how to use Redux as a way to manage state in my applications and I like it so far, but I'm having trouble assigning props dynamically to to children of a parent component.
Here is what I am working with, basic parent with children scenario:
<Layout>
<Child />
<Child />
<Child />
</Layout>
I want each child to have a unique id so childProps.id
for the first child would be 1
, the second child would be 2
and so on.
First here is the assignId
function I want to fire when the component is rendered:
export function assignId(number){
return{
type: "ASSIGN",
payload: number
}
}
Here is the reducer listening for this function:
export default function reducer(state={
id: 0
}, action){
switch (action.type){
case "ASSIGN": {
return {...state, id: action.payload}
}
}
return state
}
Finally the <Child />
component itself:
import React from "react";
import { activeBox, beginSession, unselect, assignId } from '../actions/boxActions'
export default class Child extends React.Component {
componentWillMount(){
var i = 1
this.props.dispatch(assignId(i));
i++
}
render(){
return (
<div className="box"></div>
)
}
}
componentWillMount
works. I have var i = 1
it sets childProps.id
to 1 for all of my <Child />
components. Simply, how would I make a function that makes each childProps.id
unique for each <Child />
component based on it's order within the <Layout />
parent?
Upvotes: 1
Views: 6398
Reputation: 3320
At the parent level, get your children IDs in an array, loop through them, and assign the id as a prop of the child.
Something like this:
<Layout>
{childrenIds.map((i) => { return <Child id={i} />} )}
</Layout>
Upvotes: 1
Reputation: 4375
Contrary to what others are saying, it makes good sense to assign IDs to array items in the store. When you render them you can pass this ID as the key
prop to each child component. This starts to make great sense when you insert, delete or reorder array items. React will use this key to help it find the right component that matches the array item. This can speed up rendering massively when store item indices change around.
This is the reason the key
prop exists and it's also why you should not simply use the index of the item. The index isn't the same thing as the identity.
Now, to generate and store such a unique ID, do something like this:
let nextId = 0;
function addItem(item) {
return {
type: 'ADD_ITEM',
payload: {
...item,
id: nextId++
}
};
}
function reducer(state = [], action) {
switch action.type {
case 'ADD_ITEM':
return [...state, action.payload]
break;
default:
return state;
}
}
You can then assign this ID to the key prop of each child. It'll be unique for the session and that's all you probably need. If not you can generate any other ID you like, such as a GUID. In any case, the important thing is that you want the ID to be a part of the item from the beginning and that the ID is not and should not be assigned to the component, but to the item the component is going to display. The component assumes the identity of the item found in the store and not the other way around.
Upvotes: 5
Reputation: 8376
I think you're adding complexity with zero value. The id
attribute of a DOM element has for sure to be unique, so you're on a right track, however
Child
components coming from somewhere and being reflected from an iterable, why not using Array#map
?So
render() {
const childElements = [1, 2, 3];
return (
<Layout>
<Child id="1" />
<Child id="2" />
<Child id="3" />
</Layout>
);
}
turns into
render() {
const childElements = [1, 2, 3];
return (
<Layout>
{childElements.map((id, index) => (
<Child
key={index}
id={id} />
))}
</Layout>
);
}
From your code, I can see that you want to dispatch an action to assign an element with an ID, while that ID isn't even stored anywhere. If it really isn't stored and used for any purpose, there's no need in it.
A general rule in React is to make things simple, not complicated. You have data, you reflect this data into DOM using components (and the hierarchy they form), and that's it. If you need to listen to DOM events, you use onClick
, onChange
and other props that are bound to DOM event listeners, and that's it. Once you want to use a lib that works with DOM, try to stick to refs instead of id
s, because those are guaranteed to refer to existing DOM element, and reference by id
may lead to nowhere when a component is being updated.
Upvotes: 5