Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/441.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 (新)来自嵌套组件的反应上下文不工作_Javascript_Reactjs_React Context - Fatal编程技术网

Javascript (新)来自嵌套组件的反应上下文不工作

Javascript (新)来自嵌套组件的反应上下文不工作,javascript,reactjs,react-context,Javascript,Reactjs,React Context,我对“new”React Context()有严重的问题,无法按照文档中我希望/期望的方式工作。我使用的是React v.16.8.6(升级可能需要很长时间,这是一个很大的应用程序)。我知道新旧东西之间有一点混合,但请大家不要拘泥于此 我这样做是为了尽可能灵活,但它不起作用 问题是,当涉及到contextAddToCart(..)时,它只执行空函数,而不是我在状态中定义为文档this.addToCart的函数。我在其他地方也有消费者。看起来可能是执行顺序不对。或者每次组件导入MinicartCo

我对“new”React Context()有严重的问题,无法按照文档中我希望/期望的方式工作。我使用的是React v.16.8.6(升级可能需要很长时间,这是一个很大的应用程序)。我知道新旧东西之间有一点混合,但请大家不要拘泥于此

我这样做是为了尽可能灵活,但它不起作用

问题是,当涉及到
contextAddToCart(..)
时,它只执行空函数,而不是我在状态中定义为文档
this.addToCart
的函数。我在其他地方也有消费者。看起来可能是执行顺序不对。或者每次组件导入
MinicartContext
时,它都会重置为空fn。。我不知道如何避开这件事

我将发布相关的代码,我认为这些代码最能解释它:

webpack.config.js

const APP_DIR = path.resolve(__dirname, 'src/');
module.exports = function config(env, argv = {}) {
  return {
    resolve: {
      extensions: ['.js', '.jsx'],
      modules: [
        path.resolve(__dirname, 'src/'),
        'node_modules',
      ],
      alias: {
        contexts: path.resolve(__dirname, './src/contexts.js'),
      },
import React, { Component } from 'react';
import {
  MinicartContext,
} from 'contexts';

class Header extends Component {

  render() {
    return (
      <div>
        <MinicartContainer MinicartContext={MinicartContext}>
          <Minicart MinicartContext={MinicartContext} />
        </MinicartContainer MinicartContext={MinicartContext}>

        {/* stuff */}

        <MinicartContainer MinicartContext={MinicartContext}>
          <Minicart MinicartContext={MinicartContext} />
        </MinicartContainer MinicartContext={MinicartContext}>
      </div>
    )
  }
}
export default Header;
contexts.js

import React from 'react';

export const MinicartContext = React.createContext({
  addToCart: () => {},
  getState: () => {},
});
export default class AddToCartButton extends Component {
  render (){
    return (
      <MinicartContext.Consumer>{value => {
        const {addToCart, getState} = value
        return (/*Something*/)
      }}</MinicartContext.Consumer>
    )
  }
}
const AddToCartButton = props => {
  const {addToCart, getState} = useContext(MinicartContext);
}
MinicartContainer.jsx

import React, { Component } from 'react';
import PropTypes from 'prop-types';

import {
  MinicartContext,
} from 'contexts';

export default class MinicartContainer extends Component {
  constructor(props) {
    super(props);

    this.addToCart = (product, qty) => {
      const { prices } = product;
      const { grandTotal, qtyTotal } = this.state;

      this.setState({
        grandTotal: grandTotal + prices.price,
        qtyTotal: qtyTotal + qty,
      });
    };

    this.state = {
      grandTotal: -1,
      qtyTotal: -1,
      currencyCode: '',
      addToCart: this.addToCart,
    };
  }    

  render() {
    const { children } = this.props;

    return (
      <MinicartContext.Provider value={this.state}>
        {children}
      </MinicartContext.Provider>
    );
  }
import {
  MinicartContext,
} from 'contexts';    

export default class AddToCartButton extends Component {

  addToCart(e, contextAddToCart) {
    e.preventDefault();
    const QTY = 1;
    const { product, active } = this.props; 

    // doing stuff ...   

    contextAddToCart(product, QTY);
  }

  render() {       
    return (
      <React.Fragment>
        <MinicartContext.Consumer>
          {({context, addToCart}) => (
            <div
              onClick={(e) => { this.addToCart(e, addToCart); }}    
import React,{Component}来自'React';
从“道具类型”导入道具类型;
进口{
微型车背景,
}来自“语境”;
导出默认类MinicartContainer扩展组件{
建造师(道具){
超级(道具);
this.addToCart=(产品、数量)=>{
const{prices}=产品;
const{grandTotal,qtyTotal}=this.state;
这是我的国家({
grandTotal:grandTotal+prices.price,
数量总计:数量总计+数量,
});
};
此.state={
总计:-1,
数量总计:-1,
货币代码:“”,
addToCart:this.addToCart,
};
}    
render(){
const{children}=this.props;
返回(
{儿童}
);
}
Header.jsx

const APP_DIR = path.resolve(__dirname, 'src/');
module.exports = function config(env, argv = {}) {
  return {
    resolve: {
      extensions: ['.js', '.jsx'],
      modules: [
        path.resolve(__dirname, 'src/'),
        'node_modules',
      ],
      alias: {
        contexts: path.resolve(__dirname, './src/contexts.js'),
      },
import React, { Component } from 'react';
import {
  MinicartContext,
} from 'contexts';

class Header extends Component {

  render() {
    return (
      <div>
        <MinicartContainer MinicartContext={MinicartContext}>
          <Minicart MinicartContext={MinicartContext} />
        </MinicartContainer MinicartContext={MinicartContext}>

        {/* stuff */}

        <MinicartContainer MinicartContext={MinicartContext}>
          <Minicart MinicartContext={MinicartContext} />
        </MinicartContainer MinicartContext={MinicartContext}>
      </div>
    )
  }
}
export default Header;
import React,{Component}来自'React';
进口{
微型车背景,
}来自“语境”;
类头扩展组件{
render(){
返回(
{/*东西*/}
)
}
}
导出默认标题;
AddToCartButton.jsx

import React, { Component } from 'react';
import PropTypes from 'prop-types';

import {
  MinicartContext,
} from 'contexts';

export default class MinicartContainer extends Component {
  constructor(props) {
    super(props);

    this.addToCart = (product, qty) => {
      const { prices } = product;
      const { grandTotal, qtyTotal } = this.state;

      this.setState({
        grandTotal: grandTotal + prices.price,
        qtyTotal: qtyTotal + qty,
      });
    };

    this.state = {
      grandTotal: -1,
      qtyTotal: -1,
      currencyCode: '',
      addToCart: this.addToCart,
    };
  }    

  render() {
    const { children } = this.props;

    return (
      <MinicartContext.Provider value={this.state}>
        {children}
      </MinicartContext.Provider>
    );
  }
import {
  MinicartContext,
} from 'contexts';    

export default class AddToCartButton extends Component {

  addToCart(e, contextAddToCart) {
    e.preventDefault();
    const QTY = 1;
    const { product, active } = this.props; 

    // doing stuff ...   

    contextAddToCart(product, QTY);
  }

  render() {       
    return (
      <React.Fragment>
        <MinicartContext.Consumer>
          {({context, addToCart}) => (
            <div
              onClick={(e) => { this.addToCart(e, addToCart); }}    
导入{
微型车背景,
}来自“语境”;
导出默认类AddToCartButton扩展组件{
addToCart(e,contextAddToCart){
e、 预防默认值();
常数数量=1;
const{product,active}=this.props;
//做事情。。。
contextAddToCart(产品、数量);
}
render(){
返回(
{({context,addToCart})=>(
{this.addToCart(e,addToCart);}

在我看来,您似乎还没有完全理解上下文API单词的含义

下面是我对上下文的HOC实现,也许它可以帮助您更好地理解事物是如何工作的

export const MinicartContext = React.createContext({}) // Export the Context so we can use the Consumer in class and functional components (above). Don't use the Provider from here.

// Wrap the provider to add some custom values.
export const MinicartProvider = props => {
  const addToCart = () => {
    //Add a default version here
  };
  const getState = () => {
    //Add a default version here
  };

  // Get the custom values and override with instance ones.
  const value = {addToCart, getState, ...props.value}

  return <MinicartContext.Provider value={value}>
    {props.children} 
  </MinicartContext.Provider>
} 
使用多个上下文对组件进行分类

import React from 'react';

export const MinicartContext = React.createContext({
  addToCart: () => {},
  getState: () => {},
});
export default class AddToCartButton extends Component {
  render (){
    return (
      <MinicartContext.Consumer>{value => {
        const {addToCart, getState} = value
        return (/*Something*/)
      }}</MinicartContext.Consumer>
    )
  }
}
const AddToCartButton = props => {
  const {addToCart, getState} = useContext(MinicartContext);
}
您也可以将包装器提供程序创建为类组件,并将完整状态作为值传递,但这并不必要


我建议您查看一下上下文,同时避免在同一作用域中使用相同的名称…您的AddToCartButton.jsx文件再次令人困惑:p

我遇到的问题是,我在多个位置使用
,但所有位置都应作为一个相同的名称使用。更改它使所有元素都被包装,从而使其他元素变得更加复杂元素在上下文更新时重置其状态

因此,我找到的唯一解决方案是将所有
静态
(包括状态)放在
MinicartContainer
中,并跟踪所有实例,然后在所有(需要的)实例上使用
forceUpdate()
。(因为我从来没有这样做过
this.setState
否则不会更新任何内容)

我认为新的React上下文将是Redux之类东西的一个干净的替代品,但就目前而言,它更像是一个非常模糊的规范,可以(有时)以非标准的方式替代Redux


如果你能用一个单一的提供者组件包装所有的子
消费者
s而不产生任何副作用,那么你就可以使它成为一个更干净的实现。也就是说,我不认为我所做的在任何方面都是不好的,但不是人们所期望的干净的实现应该是什么样子。而且这种方法也不是文档中也没有提到。

我认为这让人感到困惑,因为您有几个函数调用相同的函数,上下传递值,您是否尝试过减速器模式?或者只是在上下文中创建函数并根据需要使用它们?@OZZIE您确定AddToCartButton组件安装在MinicartContainer co.下吗react树中的Component?我在代码中看不到它。从您发布的代码中很难判断问题可能是什么。您可能没有正确连接到上下文。如果我不得不猜测,您可能只是对函数本身有问题。下面是一个工作示例,与您所拥有的非常接近。也许这将有助于另一件事我在回答中遗漏了这一点:在
标题.jsx
文件上,使用
微型车容器
微型车
,删除
微型车上下文
道具。在消费者中,它必须命名为“value”还是可以放任何东西?或者它必须与提供者中的名称相同?