Do I need Redux to display ItemList on the left and ItemContent on the right?

女生的网名这么多〃 提交于 2020-01-04 01:50:07

问题


Do I really need Redux to manage the app state to achieve this? If not - How do I manage/implement my routes and state for <ItemList /> and <ItemContent >/ components?

  • Should I create <ItemsListAndContent /> component and nest other components in?
  • Maybe this is the case for HOC?

What's the best approach?

To clarify app structure here is an image:

Current case and code:

My app state is passed from <App /> to <ExpenseList />

class ExpenseList extends Component {

  const details = passExpenseProps(expense){
    return (
      <div>
        <ExpenseDetails expenseProps={expense} />
      </div>

    )
  }

  render () {
    const {expenses} = this.props;
    const list = expenses.expenseList.map(expense =>
        <Segment clearing key={expense.uid} >
          <a href="" onClick={() => {this.passExpenseProps(expense)}}>
            {expense.createdAt}
          </a>
          <Button floated='right'>
            Preview / Print
          </Button>
        </Segment>
    )

    return (
        <div>

          <Grid celled='internally'>
            <Grid.Row>
              <Grid.Column width={5}>
                <div>
                  <h1>Your Expense List:</h1>
                  <Button onClick={this.props.loadSamples}>Load Sample Expenses</Button>
                  <Segment.Group raised>

                    {list}

                  </Segment.Group>
                </div>

              </Grid.Column>
              <Grid.Column width={11}>
                <Segment>

                  {details}

                </Segment>
              </Grid.Column>
            </Grid.Row>
          </Grid>

      </div>

    )
  }
}

this gives me an error:


回答1:


For a simple app, I recommend you avoid redux (and especially if you’re new to react). I would use react-router and make a component for each “screen” that has a different url. Store the state in that screen and make all of the other components use props for their data and actions.

For your example:

import React, { Component } from 'react';
import {
  BrowserRouter as Router,
  Switch,
  Route,
  Link,
} from 'react-router-dom'

import './App.css';

class ExpenseList extends Component {
    render () {
      const {expenses, selectExpense} = this.props;
      return (
        <div>{expenses.map(expense => (
          <div key={expense.id}>
            <h5>{expense.title}</h5>
            <button onClick={selectExpense(expense)}>View Details</button>
          </div>
        ))}</div>
      )
    }
  }

class ExpenseDetail extends Component {
    render () {
      const {expense} = this.props;
      return (
      <div>
        <h1>{expense.title}</h1>
        <p>${expense.amount}</p>
      </div>
      )
    }
  }



class ExpenseScreen extends Component {
  state = {expenses: [], selectedExpense: null}

  loadSamples = () => {
    // fetch from backend here

    this.setState({expenses: [
      {id: 1, title: "Expense 1", amount: 1},
      {id: 2, title: "Expense 2", amount: 2},
      {id: 3, title: "Expense 3", amount: 3},
      {id: 4, title: "Expense 4", amount: 4},
    ]})
  }

  selectExpense = (expense) => (clickEvent) => {
    this.setState({selectedExpense: expense});
  }

  render() {
    return(
    <div className="expense-container">
        <Link to="/about">About</Link>
        <div className="left-col">
          <h1>Your Expense List:</h1>
          <button onClick={this.loadSamples}>Load Sample Expenses</button>
          <ExpenseList expenses={this.state.expenses} selectExpense={this.selectExpense} />
        </div>
        <div className="right-col">
        {this.state.selectedExpense && <ExpenseDetail expense={this.state.selectedExpense} />}
  </div>
  </div>);
  }
}


 const About = () => (
    <div>
      <h2>About</h2>
      <Link to="/">Home</Link>
    </div>
  )

class App extends Component {
  render() {
    return (
      <div className="App">
        <Router>
          <Switch>
          <Route path="/" exact component={ExpenseScreen} />
          <Route path="/about" component={About} />
          </Switch>
        </Router>
      </div>
    );
  }
}

export default App;



回答2:


You don't need to use redux if your app is simple and small. You can use component states to do that. You should always start small and use redux only when your app grows big enough.


Now related your question you can keep your main state in <ItemList /> component and pass needed data to <ItemContent /> component based on which item is clicked from the list. Example

class ItemList extends Component {
  constructor(props) {
    super(props);
    this.state = {
     ...
     // you can keep your data here like
     // headings and data for the item content
    }
  }

  .
  .
  .
  // your methods
  .
  .
  .
  render() {
    const itemList = //map your list here and
    // provide a click event which will
    // render the respective <ItemContent />
    // may be using an id or some index of the array
    // depends how you want your data structure to be.
    return(
      {itemList}
      // based on which item from the list is clicked
      // you can pass different heading and state
      <ItemContent heading={...} data={...} />
    );
  }
}

Edit: Changes in your code.

class ExpenseList extends Component {

  constructor(props) {
    super(props);
    this.state = {
      currentItemId = this.props.expenses[0].uid
    }
  }

  handleItemClick = (e) => {
    const uid = e.target.id;
    this.setState({ currentItemId: uid });
  }

  details = () => {
    const { expenseList } = this.props.expenses;
    const [ expense ] = expenseList.filter(expense => {
      return expense.uid === this.state.currentItemId;
    });
    return (
      <div>
        <ExpenseDetails expenseProps={expense} />
      </div>
    )
  }

  render () {
    const { expenseList } = this.props.expenses;

    const list = expenseList.map(expense =>
        <Segment clearing key={expense.uid} >
          <a href="#" id={expense.uid} onClick={this.handleItemClick}>
            {expense.createdAt}
          </a>
          <Button floated='right'>
            Preview / Print
          </Button>
        </Segment>
    )

    return (
      <Grid celled='internally'>
        <Grid.Row>
          <Grid.Column width={5}>
            <div>
              <h1>Your Expense List:</h1>
              <Button onClick={this.props.loadSamples}>Load Sample Expenses</Button>
              <Segment.Group raised>
                {list}
              </Segment.Group>
            </div>

          </Grid.Column>
          <Grid.Column width={11}>
            <Segment>
              {details()}
            </Segment>
          </Grid.Column>
        </Grid.Row>
      </Grid>
    )
  }
}

Note: I haven't tested it.



来源:https://stackoverflow.com/questions/46821789/do-i-need-redux-to-display-itemlist-on-the-left-and-itemcontent-on-the-right

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!