简体   繁体   English

如何从 class 组件更新功能组件的 state 以便在反应中显示 map 中的项目

[英]How do I update state of a functional component from a class component in order to display items from a map in react

I have a StoreDetails functional componenet in Gatsby JS, it is rendering products conditionally from a map in graphQL that match the state value using UseState hook.我在 Gatsby JS 中有一个 StoreDetails 功能组件,它使用 UseState 钩子有条件地从 graphQL 中的 map 呈现产品,它与 state 值匹配。 I have a class component drop down menu that currently manually is populated with sku'ids that would match the condition to display in the state and map conditional statement.我有一个 class 组件下拉菜单,当前手动填充了 sku'id,这些 sku'id 将匹配 state 和 map 条件语句中显示的条件。 I want the dropdown to change the state of the functional component so the right product shows when it is selected in the drop down.我希望下拉菜单更改功能组件的 state,以便在下拉菜单中选择正确的产品时显示。 I was playing around with passing the state function as a prop, but I got rerender issues, quite stuck here.我正在玩弄通过 state function 作为道具,但我遇到了重新渲染问题,非常卡在这里。

The key is at this line {value.skuId === sku.skuId?关键在这一行{value.skuId === sku.skuId? How do I change that based on the option dropdown when it's still inside the map当它仍在 map 内时,如何根据选项下拉菜单更改它

thanks ahead of time提前感谢

Here is my code so far到目前为止,这是我的代码


import React, {useState} from 'react';
import Layout from "../components/layout"
import styled from 'styled-components';
import {loadStripe} from '@stripe/stripe-js';
// import Alert from '../components/Alert';
import { navigate } from "gatsby";
import Img from "gatsby-image"





const StoreHero = styled.section`
    width:1280px;
    margin:0 auto;
`

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

        //console.log(props);

        this.state = {test:"test",hello:"hello1",hash:props.hash}
    }
    render(){
        const { test, hello, hash } = this.state

        //console.log(hash);

        return(
            <div>{hash}</div>
        )
    }
}


class ShowItem extends React.Component {
  constructor(props) {
    super(props);
    this.state = {value: 'coconut'};

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

  handleChange(event) {
    this.setState({value: event.target.value});
    console.log(event.target.value);

    // Right here is where I want to change the state of the value variable below so
    // that the correct product is shown based on the dropdown sku selection

  }


  render() {


    return (

          <select value={this.state.value} onChange={this.handleChange}>
            <option value="sku_HAD1kUsbV3GpgW">sku_HAD1kUsbV3GpgW</option>
            <option value="sku_HACMgLjJBZFR7A">sku_HACMgLjJBZFR7A</option>
          </select>


    );
  }
}

class Product extends React.Component{

    constructor(props) {
        super(props);

        this.state = {
          stripe: null
        };

                this.loadStripeLib = this.loadStripeLib.bind(this);
                this.handleSubmit = this.handleSubmit.bind(this);
      }

      componentDidMount() {
        this.loadStripeLib()
      }

      async loadStripeLib() {
        try {
          const stripe = await loadStripe('pk_test_random');
          this.setState({ stripe });
        } catch {
          // do nothing
        }
      }

      handleSubmit(sku, productId){
          return event => {
              event.preventDefault();
              this.state.stripe.redirectToCheckout({
                items: [{sku, quantity: 1}],
                successUrl: `http://localhost:8000/store/${productId}#success`,
                cancelUrl: `http://localhost:8000/store/${productId}#cancelled`,
              }).then(function (result) {
                // Display result.error.message to your customer
                console.error(result);
              });
          }
            }


      render(){
                    const { id, currency, price, name, productId } = this.props

                    const priceFloat = (price / 100).toFixed(2)
                    const formattedPrice = Intl.NumberFormat('en-US', {
                    style: 'currency',
                    currency,
                    }).format(priceFloat)

          return(
              <form onSubmit={this.handleSubmit(id, productId)}>
                                <h2>
                                    {name} ({formattedPrice})
                                </h2>
                <button type="submit">Buy Now</button>

              </form>
          )
      }

}

const StoreDetails = ({data, location}) =>{

  const [value, setValue] = useState({
    skuId: "sku_HAD1kUsbV3GpgW"
  });



    //console.log(value);



    return(
        <Layout>
            <StoreHero>
                        <Alert test="test" hello="hello" hash={location.hash}/>

            {/* <ShowItem props={data}/> */}                                    

              {data.allDatoCmsStore.edges.map(({ node: sku }) => (
                <>
                {value.skuId === sku.skuId ?
                  <>
                    <ShowItem setValue={setValue}/>
                    <Product
                      key={sku.id}
                      id={sku.skuId}
                      productId={sku.productId}
                      currency="cad"
                      price={sku.price}
                      name={sku.title}
                    />
                    <Img fixed={sku.image.fixed}/>
                  </>
                :
                  null
                }

                </>
              ))}

            </StoreHero>
        </Layout>
    )

}

export default StoreDetails

export const query = graphql`
  query StoreDeatailsQuery($slug: String!)  {
    allDatoCmsStore(filter: {productId: {eq: $slug}}) {
      edges {
        node {
          price
          productId
          skuId
          title
          id
          image{
            fixed{
              ...GatsbyDatoCmsFixed
            }
          }
        }
      }
    }
    allStripeSku {
        edges {
          node {
            id
            currency
            price
            attributes {
              name
            }
            image
            localFiles {
              childImageSharp {
                fixed(width: 125) {
                  ...GatsbyImageSharpFixed
                }
              }
            }
          }
        }
      }
  }
`

Looks like I was overcomplicating it, I have more to do, but changing it to this fixed it for me看起来我把它复杂化了,我还有更多工作要做,但是把它改成这个对我来说是固定的

const StoreDetails = ({data, location}) =>{

  const [value, setValue] = useState({
    skuId: "sku_HAD1kUsbV3GpgW"
  });


  const run = (event) =>{
    console.log(event);
    setValue({skuId:event})
  }


    return(
        <Layout>
            <StoreHero>
                        <Alert test="test" hello="hello" hash={location.hash}/>

            {/* <ShowItem props={data}/> */}                                    

              {data.allDatoCmsStore.edges.map(({ node: sku }) => (
                <>
                {value.skuId === sku.skuId ?
                  <>
                  <select onChange={(event) => run(event.target.value)}>
                    <option value="sku_HAD1kUsbV3GpgW">sku_HAD1kUsbV3GpgW</option>
                    <option value="sku_HACMgLjJBZFR7A">sku_HACMgLjJBZFR7A</option>
                  </select>
                    {/* <ShowItem setValue={setValue}/> */}
                    <Product
                      key={sku.id}
                      id={sku.skuId}
                      productId={sku.productId}
                      currency="cad"
                      price={sku.price}
                      name={sku.title}
                    />
                    <Img fixed={sku.image.fixed}/>
                  </>
                :
                  null
                }

                </>
              ))}

            </StoreHero>
        </Layout>
    )

}

React UI will change by reacting to state changes. React UI 将通过响应 state 更改来更改。 if two child component need the same data (in this case the selected value).如果两个子组件需要相同的数据(在这种情况下是选定的值)。 then the state of selected value should be on the parent component (in StoreDetails ) so the Product will change when the value state on StoreDetails is changed by the function sent to the onChange as props.那么选定值的 state 应该在父组件上(在StoreDetails中),因此当 StoreDetails 上的StoreDetails的值被onChange发送到的道具更改时, Product将发生变化。

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

相关问题 如何使用useContext从功能组件更新class组件的state - How to update state of class component from functional component using useContext 是否可以从 React Class 组件到功能组件进行道具钻取? - Is it possible to do prop drilling from React Class Component to Functional Component? 我想将此代码从 class 组件更改为反应中的功能组件 - I want to change this code from class component to functional component in react React:如何强制状态在功能组件中更新? - React: how can I force state to update in a functional component? 如何在功能组件中立即更新反应状态? - How to update react state immediately in functional component? 如何在 React 功能组件中立即更新状态? - How to update the state immediately in React functional component? 如何从 React 中的子组件更新父组件(功能) - How to update Parent component from Child component in React (Functional) 我如何使用上下文在React中的类和功能组件之间共享状态? - How do I use context to share state between a class and a functional component in react? 从父组件 React JS 调用 map function 时如何更新子组件的 state - How to update state of child component when it get called in map function from parent component React JS 更改为 React State 不会更新功能组件中的显示 - Change to React State doesn't update display in functional component
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM