Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/mercurial/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 上下文API中的ReactJS异步axios_Javascript_Reactjs_Async Await_Axios - Fatal编程技术网

Javascript 上下文API中的ReactJS异步axios

Javascript 上下文API中的ReactJS异步axios,javascript,reactjs,async-await,axios,Javascript,Reactjs,Async Await,Axios,我从context.js中的RESTAPI获取数据。我将数据分配给state。以下是context.js中的代码: export class AppProvider extends Component { state = { products: [], cart: [], dispatch: action => this.setState(state => reducer(state, action)) } f

我从
context.js
中的RESTAPI获取数据。我将数据分配给state。以下是
context.js
中的代码:

export class AppProvider extends Component {
    state = {
        products: [],
        cart: [],
        dispatch: action => this.setState(state => reducer(state, action))
    }

    fetchData = async () => {
        const products = await axios.get('http://127.0.0.1:4000/product/all', { headers: { "Access-Control-Allow-Origin": "*" } })
        this.setState({
            products: products.data
        })
    }

    componentDidMount(){
        this.fetchData();
    }

    render() {
        return (
            <AppContext.Provider value={this.state}>
                {this.props.children}
            </AppContext.Provider>
        )
    }
}

您的
AppProvider
组件是正确的,唯一的问题是您从API获取结果,然后在
componentDidMount
中执行该操作,而该组件应该是正确的

但是,当您刷新页面时,
AppProvider
中的设置将重置为初始值,并且由于您已经在
ProductDetail
组件上,因此您甚至在API请求提供产品值之前就尝试访问产品值,因此

const filteredProduct = products.filter(p => p.id == props.match.params.id)
将返回您可以清空的数组

出现此问题的原因是您试图访问
filteredProduct[0]。image
和类似的其他属性

这里的解决方案是使用loadingState并呈现loader,直到数据可用为止

另外,请确保数据可用时,
filteredProduct
永远不会为空

export class AppProvider extends Component {
    state = {
        isLoading: true,
        products: [],
        cart: [],
        dispatch: action => this.setState(state => reducer(state, action))
    }

    fetchData = async () => {
        const products = await axios.get('http://127.0.0.1:4000/product/all', { headers: { "Access-Control-Allow-Origin": "*" } })
        this.setState({
            isLoading: false,
            products: products.data
        })
    }

    componentDidMount(){
        this.fetchData();
    }

    render() {
        return (
            <AppContext.Provider value={this.state}>
                {this.props.children}
            </AppContext.Provider>
        )
    }
}
导出类AppProvider扩展组件{
状态={
孤岛加载:是的,
产品:[],
购物车:[],
dispatch:action=>this.setState(state=>reducer(state,action))
}
fetchData=async()=>{
const products=等待axios.get('http://127.0.0.1:4000/product/all“,{标头:{“访问控制允许源”:“*”})
这是我的国家({
孤岛加载:false,
产品:产品数据
})
}
componentDidMount(){
这是fetchData();
}
render(){
返回(
{this.props.children}
)
}
}
在产品细节方面

const ProductDetail = props => {
    const [inputValue, setInputValue] = useState(1);


    const preventNegative = e => {
        const value = e.target.value.replace(/[^\d]/, '');
        if (parseInt(value) !== 0) {
            setInputValue(value);
        }
    }

    const addToCart = (e, productID) => {
        // eslint-disable-next-line array-callback-return
        const product = products.filter(p => {
            // eslint-disable-next-line eqeqeq
            if (p.id == productID) {
                return p
            }
        })
        console.log(product);
        dispatch({
            type: 'ADD_TO_CART',
            payload: [product, inputValue]
        })
        toast.success("The product has been added to cart successfully !", {
            position: toast.POSITION.TOP_CENTER,
            autoClose: 2500,
            transition: Slide
        })
    }



    const { products, dispatch, isLoading } = useContext(AppContext)
    if(isLoading) return <div>Loading...</div>

    const filteredProduct = products.filter(p => p.id == props.match.params.id)

    return (
        <React.Fragment>
            <main className="mt-5 pt-4">
                <div className="container dark-grey-text mt-5">
                    <div className="row wow fadeIn">
                        <div className="col-md-6 mb-4">
                            <img src={filteredProduct[0].image} className="img-fluid" alt="" />
                        </div>
                        <div className="col-md-6 mb-4">
                            <div className="p-4">
                                <div className="mb-3">
                                    <Badge color="primary">New</Badge>
                                    <Badge color="success">Best seller</Badge>
                                    <Badge color="danger">{filteredProduct[0].discountRate}% OFF</Badge>
                                </div>
                                <h2 className="h2">{filteredProduct[0].title}</h2>
                                <p className="lead">
                                    <span className="mr-1">
                                        <del>${filteredProduct[0].prevPrice}</del>
                                    </span>
                                    <span>${filteredProduct[0].price}</span>
                                </p>
                                <p className="text-muted">
                                    {filteredProduct[0].detail}
                                </p>
                                <form className="d-flex justify-content-left">
                                    <input
                                        min="1"
                                        onChange={(e) => preventNegative(e)}
                                        value={inputValue}
                                        type="number"
                                        aria-label="Search"
                                        className="form-control"
                                        style={{ width: '100px' }} />

                                    <Button onClick={(e) => addToCart(e, filteredProduct[0].id)} color="primary">Add to Cart <FontAwesomeIcon icon={faShoppingCart} /> </Button>

                                </form>
                            </div>
                        </div>
                    </div>
                </div>
            </main>
        </React.Fragment>

    )
}
export default ProductDetail;
constproductdetail=props=>{
常量[inputValue,setInputValue]=useState(1);
const prevent negative=e=>{
const value=e.target.value.replace(/[^\d]/,“”);
if(parseInt(值)!==0){
设置输入值(值);
}
}
const addToCart=(e,productID)=>{
//eslint禁用下一行数组回调返回
const product=products.filter(p=>{
//eslint禁用下一行EQEQ
if(p.id==productID){
返回p
}
})
控制台日志(产品);
派遣({
键入:“将\添加到\购物车”,
有效负载:[产品,输入值]
})
toast.success(“产品已成功添加到购物车!”{
位置:toast.position.TOP_居中,
自动关闭:2500,
过渡:幻灯片
})
}
const{products,dispatch,isLoading}=useContext(AppContext)
如果(正在加载)返回加载。。。
const filteredProduct=products.filter(p=>p.id==props.match.params.id)
返回(
新的
畅销书
{filteredProduct[0]。取消集中度}%OFF
{filteredProduct[0]。标题}

${filteredProduct[0]。prevPrice} ${filteredProduct[0]。价格}

{filteredProduct[0]。详细信息}

(e)} 值={inputValue} type=“编号” aria label=“搜索” className=“表单控件” 样式={{width:'100px'}}/> addToCart(e,filteredProduct[0].id)}color=“primary”>添加到购物车 ) } 导出默认ProductDetail;
get请求的解析是否正确?如果您在设置状态之前登录产品,它看起来正确吗?页面刷新的预期行为是什么??将数据保存在localstorage中,并从中初始化。
const ProductDetail = props => {
    const [inputValue, setInputValue] = useState(1);


    const preventNegative = e => {
        const value = e.target.value.replace(/[^\d]/, '');
        if (parseInt(value) !== 0) {
            setInputValue(value);
        }
    }

    const addToCart = (e, productID) => {
        // eslint-disable-next-line array-callback-return
        const product = products.filter(p => {
            // eslint-disable-next-line eqeqeq
            if (p.id == productID) {
                return p
            }
        })
        console.log(product);
        dispatch({
            type: 'ADD_TO_CART',
            payload: [product, inputValue]
        })
        toast.success("The product has been added to cart successfully !", {
            position: toast.POSITION.TOP_CENTER,
            autoClose: 2500,
            transition: Slide
        })
    }



    const { products, dispatch, isLoading } = useContext(AppContext)
    if(isLoading) return <div>Loading...</div>

    const filteredProduct = products.filter(p => p.id == props.match.params.id)

    return (
        <React.Fragment>
            <main className="mt-5 pt-4">
                <div className="container dark-grey-text mt-5">
                    <div className="row wow fadeIn">
                        <div className="col-md-6 mb-4">
                            <img src={filteredProduct[0].image} className="img-fluid" alt="" />
                        </div>
                        <div className="col-md-6 mb-4">
                            <div className="p-4">
                                <div className="mb-3">
                                    <Badge color="primary">New</Badge>
                                    <Badge color="success">Best seller</Badge>
                                    <Badge color="danger">{filteredProduct[0].discountRate}% OFF</Badge>
                                </div>
                                <h2 className="h2">{filteredProduct[0].title}</h2>
                                <p className="lead">
                                    <span className="mr-1">
                                        <del>${filteredProduct[0].prevPrice}</del>
                                    </span>
                                    <span>${filteredProduct[0].price}</span>
                                </p>
                                <p className="text-muted">
                                    {filteredProduct[0].detail}
                                </p>
                                <form className="d-flex justify-content-left">
                                    <input
                                        min="1"
                                        onChange={(e) => preventNegative(e)}
                                        value={inputValue}
                                        type="number"
                                        aria-label="Search"
                                        className="form-control"
                                        style={{ width: '100px' }} />

                                    <Button onClick={(e) => addToCart(e, filteredProduct[0].id)} color="primary">Add to Cart <FontAwesomeIcon icon={faShoppingCart} /> </Button>

                                </form>
                            </div>
                        </div>
                    </div>
                </div>
            </main>
        </React.Fragment>

    )
}
export default ProductDetail;