[英]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.