admin管理员组

文章数量:1025527

I'm slowly getting the knack (I think) for react. What I'm trying to do is display a list in one ponent and then make each list item (item 1, item 2, etc..) clickable so that when it is clicked, it can move back and forth between the two <ItemList /> ponents. What I have is below, I think where my problem is setting the state on the first list in the handleEvent().

class SingleItem extends React.Component {
  render() {
    let data = this.props.data;

    return (
        <li>
            <div> {data.name} </div>
        </li>
    );
  }
}

class ItemList extends React.Component {
   render() {
     let itemArr = this.props.items;

     let listItems = itemArr.map((itemObj) => {
        return <SingleItem key={itemObj.id} data={itemObj}/>;
});

    return (
        <ul onClick={props.handleEvent}>
            {listItems}
        </ul>
    );
  }
}

class App extends React.Component {
constructor(props) {
    super(props);

    this.state = {
        boxOne: {listItems},
        boxTwo:''
    };

    this.handleEvent = this.handleEvent.bind(this);
}

handleEvent() {
    this.setState({
        boxOne: this.state.boxTwo,
        boxTwo: this.state.boxOne
    });
}
render() {
    return (
        <div>
            <ItemList items={this.state.boxOne} />
            <ItemList items={this.state.boxTwo} />
        </div>
    );
  }
};

var items = [
  {name: "Item 1", id: 1},
  {name: "Item 2", id: 2},
  {name: "Item 3", id: 3},
  {name: "Item 4", id: 4},
]

ReactDOM.render(<App />, document.getElementById('root'));

I'm slowly getting the knack (I think) for react. What I'm trying to do is display a list in one ponent and then make each list item (item 1, item 2, etc..) clickable so that when it is clicked, it can move back and forth between the two <ItemList /> ponents. What I have is below, I think where my problem is setting the state on the first list in the handleEvent().

class SingleItem extends React.Component {
  render() {
    let data = this.props.data;

    return (
        <li>
            <div> {data.name} </div>
        </li>
    );
  }
}

class ItemList extends React.Component {
   render() {
     let itemArr = this.props.items;

     let listItems = itemArr.map((itemObj) => {
        return <SingleItem key={itemObj.id} data={itemObj}/>;
});

    return (
        <ul onClick={props.handleEvent}>
            {listItems}
        </ul>
    );
  }
}

class App extends React.Component {
constructor(props) {
    super(props);

    this.state = {
        boxOne: {listItems},
        boxTwo:''
    };

    this.handleEvent = this.handleEvent.bind(this);
}

handleEvent() {
    this.setState({
        boxOne: this.state.boxTwo,
        boxTwo: this.state.boxOne
    });
}
render() {
    return (
        <div>
            <ItemList items={this.state.boxOne} />
            <ItemList items={this.state.boxTwo} />
        </div>
    );
  }
};

var items = [
  {name: "Item 1", id: 1},
  {name: "Item 2", id: 2},
  {name: "Item 3", id: 3},
  {name: "Item 4", id: 4},
]

ReactDOM.render(<App />, document.getElementById('root'));
Share Improve this question asked Jun 29, 2017 at 23:41 Bobby TablesBobby Tables 1634 silver badges18 bronze badges 10
  • I see you have items array at the bottom, what is listItems in the App ponent? – FuriousD Commented Jun 29, 2017 at 23:58
  • There are several problems with you code, it's also not very clear what you are trying to do. Please describe exactly what you expect and what failed. – webdeb Commented Jun 29, 2017 at 23:59
  • What you are trying to achieve is relatively straight forward, however yes, I agree with @webdeb, there are some problems with your code. Can you please set up a fiddle – FuriousD Commented Jun 30, 2017 at 0:00
  • 1 For example this line cannot work boxOne: {listItems}, – webdeb Commented Jun 30, 2017 at 0:00
  • @FuriousD thank you for your responses, setting up a fiddle now – Bobby Tables Commented Jun 30, 2017 at 0:05
 |  Show 5 more ments

1 Answer 1

Reset to default 3

This is how it could be done..

So, I am passing the whole items array to all ItemLists, but I am also passing the state, which is just an array with ids of the included items in that list, check out the logic below and try to understand, it's easy actually..

class SingleItem extends React.Component {
  render() {
    let data = this.props.data;

    return (
        <li onClick={this.props.onClick}>
            <div> {data.name} </div>
        </li>
    );
  }
}

class ItemList extends React.Component {
   render() {
     let itemArr = this.props.allItems;
     let myItems = this.props.items;
     let handleEvent = this.props.handleEvent;

     let listItems = itemArr.map((itemObj) => {
        if (!myItems.includes(itemObj.id)) return null;

        return <SingleItem 
          key={itemObj.id}
          data={itemObj}
          onClick={() => handleEvent(itemObj.id)}
        />;
     });

     return (
        <ul>
            {listItems}
        </ul>
     );
   }
}

class App extends React.Component {
constructor(props) {
    super(props);

    this.state = {
        boxOne: props.items.map(item => item.id), // init the boxes with itemIds
        boxTwo: []
    };

    this.handleEvent = this.handleEvent.bind(this);
}

handleEvent(itemId) {
    const isInBoxOne = this.state.boxOne.includes(itemId);

    // Heres the magic, if the item is in the first Box, filter it out,
    // and put into the second, otherwise the other way around..
    this.setState({
        boxOne: isInBoxOne
          ? this.state.boxOne.filter(i => i !== itemId)
          : [ ...this.state.boxOne, itemId ]
        boxTwo: isInBoxOne
          ? [ ...this.state.boxTwo, itemId ]
          : this.state.boxTwo.filter(i => i !== itemId)
    });
}
render() {
    return (
        <div>
            <ItemList handleEvent={this.handleEvent} items={this.state.boxOne} allItems={this.props.items} />
            <ItemList handleEvent={this.handleEvent} items={this.state.boxTwo} allItems={this.props.items} />
        </div>
    );
  }
};

var items = [
  {name: "Item 1", id: 1},
  {name: "Item 2", id: 2},
  {name: "Item 3", id: 3},
  {name: "Item 4", id: 4},
]

ReactDOM.render(
  // Pass the initial items to your App
  <App items={items} />,
  document.getElementById('root')
);

I'm slowly getting the knack (I think) for react. What I'm trying to do is display a list in one ponent and then make each list item (item 1, item 2, etc..) clickable so that when it is clicked, it can move back and forth between the two <ItemList /> ponents. What I have is below, I think where my problem is setting the state on the first list in the handleEvent().

class SingleItem extends React.Component {
  render() {
    let data = this.props.data;

    return (
        <li>
            <div> {data.name} </div>
        </li>
    );
  }
}

class ItemList extends React.Component {
   render() {
     let itemArr = this.props.items;

     let listItems = itemArr.map((itemObj) => {
        return <SingleItem key={itemObj.id} data={itemObj}/>;
});

    return (
        <ul onClick={props.handleEvent}>
            {listItems}
        </ul>
    );
  }
}

class App extends React.Component {
constructor(props) {
    super(props);

    this.state = {
        boxOne: {listItems},
        boxTwo:''
    };

    this.handleEvent = this.handleEvent.bind(this);
}

handleEvent() {
    this.setState({
        boxOne: this.state.boxTwo,
        boxTwo: this.state.boxOne
    });
}
render() {
    return (
        <div>
            <ItemList items={this.state.boxOne} />
            <ItemList items={this.state.boxTwo} />
        </div>
    );
  }
};

var items = [
  {name: "Item 1", id: 1},
  {name: "Item 2", id: 2},
  {name: "Item 3", id: 3},
  {name: "Item 4", id: 4},
]

ReactDOM.render(<App />, document.getElementById('root'));

I'm slowly getting the knack (I think) for react. What I'm trying to do is display a list in one ponent and then make each list item (item 1, item 2, etc..) clickable so that when it is clicked, it can move back and forth between the two <ItemList /> ponents. What I have is below, I think where my problem is setting the state on the first list in the handleEvent().

class SingleItem extends React.Component {
  render() {
    let data = this.props.data;

    return (
        <li>
            <div> {data.name} </div>
        </li>
    );
  }
}

class ItemList extends React.Component {
   render() {
     let itemArr = this.props.items;

     let listItems = itemArr.map((itemObj) => {
        return <SingleItem key={itemObj.id} data={itemObj}/>;
});

    return (
        <ul onClick={props.handleEvent}>
            {listItems}
        </ul>
    );
  }
}

class App extends React.Component {
constructor(props) {
    super(props);

    this.state = {
        boxOne: {listItems},
        boxTwo:''
    };

    this.handleEvent = this.handleEvent.bind(this);
}

handleEvent() {
    this.setState({
        boxOne: this.state.boxTwo,
        boxTwo: this.state.boxOne
    });
}
render() {
    return (
        <div>
            <ItemList items={this.state.boxOne} />
            <ItemList items={this.state.boxTwo} />
        </div>
    );
  }
};

var items = [
  {name: "Item 1", id: 1},
  {name: "Item 2", id: 2},
  {name: "Item 3", id: 3},
  {name: "Item 4", id: 4},
]

ReactDOM.render(<App />, document.getElementById('root'));
Share Improve this question asked Jun 29, 2017 at 23:41 Bobby TablesBobby Tables 1634 silver badges18 bronze badges 10
  • I see you have items array at the bottom, what is listItems in the App ponent? – FuriousD Commented Jun 29, 2017 at 23:58
  • There are several problems with you code, it's also not very clear what you are trying to do. Please describe exactly what you expect and what failed. – webdeb Commented Jun 29, 2017 at 23:59
  • What you are trying to achieve is relatively straight forward, however yes, I agree with @webdeb, there are some problems with your code. Can you please set up a fiddle – FuriousD Commented Jun 30, 2017 at 0:00
  • 1 For example this line cannot work boxOne: {listItems}, – webdeb Commented Jun 30, 2017 at 0:00
  • @FuriousD thank you for your responses, setting up a fiddle now – Bobby Tables Commented Jun 30, 2017 at 0:05
 |  Show 5 more ments

1 Answer 1

Reset to default 3

This is how it could be done..

So, I am passing the whole items array to all ItemLists, but I am also passing the state, which is just an array with ids of the included items in that list, check out the logic below and try to understand, it's easy actually..

class SingleItem extends React.Component {
  render() {
    let data = this.props.data;

    return (
        <li onClick={this.props.onClick}>
            <div> {data.name} </div>
        </li>
    );
  }
}

class ItemList extends React.Component {
   render() {
     let itemArr = this.props.allItems;
     let myItems = this.props.items;
     let handleEvent = this.props.handleEvent;

     let listItems = itemArr.map((itemObj) => {
        if (!myItems.includes(itemObj.id)) return null;

        return <SingleItem 
          key={itemObj.id}
          data={itemObj}
          onClick={() => handleEvent(itemObj.id)}
        />;
     });

     return (
        <ul>
            {listItems}
        </ul>
     );
   }
}

class App extends React.Component {
constructor(props) {
    super(props);

    this.state = {
        boxOne: props.items.map(item => item.id), // init the boxes with itemIds
        boxTwo: []
    };

    this.handleEvent = this.handleEvent.bind(this);
}

handleEvent(itemId) {
    const isInBoxOne = this.state.boxOne.includes(itemId);

    // Heres the magic, if the item is in the first Box, filter it out,
    // and put into the second, otherwise the other way around..
    this.setState({
        boxOne: isInBoxOne
          ? this.state.boxOne.filter(i => i !== itemId)
          : [ ...this.state.boxOne, itemId ]
        boxTwo: isInBoxOne
          ? [ ...this.state.boxTwo, itemId ]
          : this.state.boxTwo.filter(i => i !== itemId)
    });
}
render() {
    return (
        <div>
            <ItemList handleEvent={this.handleEvent} items={this.state.boxOne} allItems={this.props.items} />
            <ItemList handleEvent={this.handleEvent} items={this.state.boxTwo} allItems={this.props.items} />
        </div>
    );
  }
};

var items = [
  {name: "Item 1", id: 1},
  {name: "Item 2", id: 2},
  {name: "Item 3", id: 3},
  {name: "Item 4", id: 4},
]

ReactDOM.render(
  // Pass the initial items to your App
  <App items={items} />,
  document.getElementById('root')
);

本文标签: javascriptReactjsMoving a list item to another listStack Overflow