admin管理员组

文章数量:1289831

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 ponent.

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 ponent 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 /> ponent itself:

import React from "react";

import { activeBox, beginSession, unselect, assignId } from '../actions/boxActions'

export default class Child extends React.Component {
  
  ponentWillMount(){
    var i = 1

    this.props.dispatch(assignId(i));

    i++

  }

  render(){

    return (
    <div className="box"></div>
    )
  }
}

ponentWillMount works. I have var i = 1 it sets childProps.id to 1 for all of my <Child /> ponents. Simply, how would I make a function that makes each childProps.id unique for each <Child /> ponent based on it's order within the <Layout /> parent?

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 ponent.

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 ponent 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 /> ponent itself:

import React from "react";

import { activeBox, beginSession, unselect, assignId } from '../actions/boxActions'

export default class Child extends React.Component {
  
  ponentWillMount(){
    var i = 1

    this.props.dispatch(assignId(i));

    i++

  }

  render(){

    return (
    <div className="box"></div>
    )
  }
}

ponentWillMount works. I have var i = 1 it sets childProps.id to 1 for all of my <Child /> ponents. Simply, how would I make a function that makes each childProps.id unique for each <Child /> ponent based on it's order within the <Layout /> parent?

Share Improve this question edited Mar 27, 2021 at 12:57 halfer 20.5k19 gold badges109 silver badges202 bronze badges asked Sep 9, 2016 at 23:25 m00sacam00saca 3631 gold badge8 silver badges22 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 5

I think you're adding plexity with zero value. The id attribute of a DOM element has for sure to be unique, so you're on a right track, however

  • in React, you don't manage elements by their IDs; take a look at references to corresponding DOM elements instead,
  • generating a globally unique identifier es at cost of maintaining that generating function, and
  • if you plan to have an arbitrary number of Child ponents ing 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 plicated. You have data, you reflect this data into DOM using ponents (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 ids, because those are guaranteed to refer to existing DOM element, and reference by id may lead to nowhere when a ponent is being updated.

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 ponent. 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 ponent 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 ponent, but to the item the ponent is going to display. The ponent assumes the identity of the item found in the store and not the other way around.

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>

本文标签: javascriptAssign unique id to component as it renders using ReduxStack Overflow