简体   繁体   English

如何将prop传递给可变长度的子级数组中的子级组件?

[英]How can I pass a prop to a child component, in a variable length array of children?

How can I fire a callback in a child component that will then pass data to a sibling component, in a specific position of the array of component children? 如何在子组件中触发回调,然后将数据传递到子组件数组中特定位置的同级组件中?

I have 3 components, App, Col, and Task. 我有3个组件,App,Col和Task。 The hierarchy is that the App contains any number of Column component, which each in turn contain any number of Task components. 层次结构是,App包含任意数量的Column组件,而每个组件又包含任意数量的Task组件。 The high level goal is to move a Task from one Column, to a sibling, at the firing of a callback. 高层目标是在触发回调时将“任务”从一列移动到同级。

However the parent component, App, doesn't seem to have any knowledge of which Column component lives at which Index. 但是,父组件App似乎不了解哪个Column组件位于哪个Index。 Codepen for easy viewing Codepen易于查看

class App extends React.Component {
constructor() {
    super();
    this.state = {
    cols: [
        'a',
        'b',
        'c',
        'd',
    ]
    }
}

moveCard = (dir) => {
    console.log(dir);
    console.log(this.state);
}

render() {
    return (
    <div className="main" style={{
        gridTemplateColumns: 'repeat('+this.state.cols.length+', 1fr)',
    }}>
        {this.state.cols.map((col, i) => <Column key={i} moveCard={this.moveCard} name={col} />)}
    </div>
    );
}
} 

const Task = ({text, moveCard}) => {
return (
    <div className="card">
    <div onClick={e => moveCard(e, -1)}>{'<'}</div>
    <div>{text}</div>
    <div onClick={e => moveCard(e, 1)}>{'>'}</div>
    </div>
);
};

class Column extends React.Component {
constructor(props) {
    super();
    this.state = {
    tasks: ['a', 'b'],
    }
}

render() {
    return (
    <div className="col">
        <header>{this.props.name}</header>
        {this.state.tasks.map((tasktText, id) => <Task key={id} text={tasktText} moveCard={e => {
        const updatedState = this.state.tasks;
        updatedState.splice(updatedState.indexOf(tasktText), 1);
        this.setState({
            tasks: updatedState,
        });
        this.props.moveCard(tasktText);
        }} />)}
    </div>
    );
}
}

The task is removed from the column correctly, however the parent most component function moveCard has all the pertinent information, but no reference to each children, as they are simply mapped in the render call. 该任务已从列中正确删除,但是最主要的父函数moveCard具有所有相关信息,但没有对每个子项的引用,因为它们仅在render调用中映射。 How should I restructure my code so that for example, when the right arrow is clicked on the top task in column 1, it disappears from column one, and reappears at the bottom of column 2? 我应该如何重组代码,例如,当在第1列的顶部任务上单击右箭头时,它会从第1列消失,并重新出现在第2列的底部?

My approach would be to keep all the column and task information in the state of the <App /> component. 我的方法是将所有列和任务信息保持在<App />组件的状态下。

The moveCard() prop in <Column /> should hand over the relevant task info; <Column />moveCard()道具应移交相关任务信息; Title, old column and new column. 标题,旧列和新列。

The handler in <App /> then updates its state (= move task to new column) – the columns get updated. 然后, <App />的处理程序更新其状态(=将任务移至新列)–列将更新。

Move all of the state to one place to manage. 将所有状态移到一个位置进行管理。 An example would be to move all data and indexes to the App component. 一个示例是将所有数据和索引移动到App组件。 An example is here: 一个例子在这里:

https://stackblitz.com/edit/react-uz7xyq https://stackblitz.com/edit/react-uz7xyq

This is using Context API to prevent prop drilling. 这是使用Context API来防止道具钻探的。 Redux would be a good mechanism for managing this as it grows 随着它的增长, Redux将是管理它的好机制

this.state = {
  cols: [
    { name: 'A', tasks: ['A', 'B']},
    { name: 'B', tasks: ['C', 'D']},
    { name: 'C', tasks: ['E', 'F']}
  ]
};

this.state.move = (isRight, colName, taskName) => {
  const index = this.state.cols.findIndex(x => x.name === colName);
  if ((!isRight && index > 0) || (isRight && index < this.state.cols.length - 1)) {
    this.state.cols[index].tasks = this.state.cols[index].tasks.filter(x => x !== taskName);
    const index2 = isRight ? 1 : -1;
    this.state.cols[index + index2].tasks = [...this.state.cols[index + index2].tasks, taskName];
    this.setState({ cols: this.state.cols });
  }
};

(Ideally you should also not mutate state as I have done) (理想情况下,您也不应像我一样更改状态)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM