Ricky
Ricky

Reputation: 777

Child component not updating in React

Help! My child component is not updating in my react app!

I want to bring cartNumber to the page component which then is passed onto header component but the number doesn't even show up!

Parent component

class Shop extends Component {
  constructor(props) {
    super(props);
    this.state = {
      merchants: [],
      error: null,
      loading: true,
      order: []
    };
  }

  componentWillMount() {
    Meteor.call("merchants.getMerchants", (error, response) => {
      if (error) {
        this.setState(() => ({ error: error }));
      } else {
        this.setState(() => ({ merchants: response }));
      }
    });
  }

  componentDidMount() {
    setTimeout(() => this.setState({ loading: false }), 800); // simulates loading of data
  }

  goBack = () => this.props.history.push("/");
  goCart = () => {
    try {
      Orders.insert(this.state.order), this.props.history.push("/cart");
    } catch (error) {
      throw new Meteor.Error("there was an error", error);
    }
  };

  onAddToCart(cartItem) {
    let { order } = this.state;
    order.push(cartItem);
    console.log(order.length);
  }

  render() {
    const { loading } = this.state;
    const { merchants, error } = this.state;
    const { data } = this.state;
    const { order } = this.state;

    const getProductsFromMerchant = ({ products, brands }) =>
      products.map(({ belongsToBrand, ...product }) => ({
        ...product,
        brand: brands[belongsToBrand]
      }));

    const products = merchants.reduce(
      (acc, merchant) => [...acc, ...getProductsFromMerchant(merchant)],
      []
    );

    if (loading) {
      return (
        <Page
          pageTitle="Shop"
          history
          goBack={this.goBack}
          goCart={this.goCart}
        >
          <div className="loading-page">
            <i
              className="fa fa-spinner fa-spin fa-3x fa-fw"
              aria-hidden="true"
            />
            <br /> <br />
            <span>Loading...</span>
          </div>
        </Page>
      );
    }

    return (
      <Page
        pageTitle="Shop"
        history
        goBack={this.goBack}
        goCart={this.goCart}
        cartNumber={order.length}
      >
        <div className="shop-page">
          {products.map(({ id, ...product }) =>
            <Product
              {...product}
              key={id}
              history
              onAddToCart={this.onAddToCart.bind(this)}
            />
          )}
        </div>
      </Page>
    );
  }
}

export default Shop;

Here is the page component which contains the header component

export const Page = ({
  children,
  pageTitle,
  history,
  goBack,
  goCart,
  cartNumber
}) =>
  <div className="page">
    <Header goBack={goBack} goCart={goCart} history cartNumber>
      {pageTitle}
    </Header>
    <main>
      <MuiThemeProvider>
        {children}
      </MuiThemeProvider>
    </main>
    <Footer />
  </div>;

export default Page;

And Finally this is the header where I want to bring the cartNumber into.

const Header = ({ children, goBack, goCart, cartNumber, pageTitle }) =>
  <header>
    <button onClick={goBack} className="back-button">
      {/* Image added here to show image inclusion, prefer inline-SVG. */}
      <img alt="Back" src={`/icon/header/back-white.svg`} />
    </button>
    <h1>
      {children}
    </h1>
    <div className="right-content">
      ( {cartNumber} )
      <i
        className="fa fa-shopping-cart fa-2x"
        aria-hidden="true"
        onClick={goCart}
      />
    </div>
  </header>;
export default withRouter(Header);

Upvotes: 0

Views: 68

Answers (1)

Andy Ray
Andy Ray

Reputation: 32056

You're passing cartNumber as a boolean:

<Header goBack={goBack} goCart={goCart} history cartNumber>

Pass it as a value:

<Header goBack={goBack} goCart={goCart} history={history} cartNumber={cartNumber}>

Upvotes: 1

Related Questions