【问题标题】:React Context - setState with onClick inside ConsumerReact Context - setState 与消费者内部的 onClick
【发布时间】:2019-08-11 11:45:05
【问题描述】:

我已经实现了 React Context API,我正在尝试通过子组件中的 onClick 函数更新 Provider 中定义的状态。

这是我到目前为止所做的,在 App.js 我有:

import { createContext } from 'react';
const MyContext = React.createContext();
export class MyProvider extends Component {
    state = {
        currPrj: ''
    }

    handleBtnClick = prjCode => {

        this.setState({
            currPrj: prjCode
        })

    }

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

export const MyComsumer = MyContext.Consumer;

在我的子组件中,我有:

import React, { Component } from "react";
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
import { MyComsumer } from "../../index";

export class ProjectCard extends Component {

  constructor(props) {
    super(props);

    this.state = {
      // currPrj: ''
    };
  }

  render() {
    return (
      <MyComsumer>
        {(context) => (
          <div className="card card-project">
          <p>{context.state.currPrj}</p>
            <div className="content">
              <div className="author">
                <Link to={ `projects/${this.props.code}/detail/info` } onClick={() => handleBtnClick(this.props.code) }>
                  <h4 className="title">
                    {this.props.title}
                  </h4>
                </Link>
              </div>
          </div>
        )}
      </MyComsumer>
    );
  }
}

export default ProjectCard;

这样我得到以下错误

Failed to compile
./src/components/ProjectCard/ProjectCard.jsx
  Line 32:  'handleBtnClick' is not defined  no-undef

Search for the keywords to learn more about each error.

我不明白为什么,因为:

<p>{context.state.currPrj}</p>

没有错误...

另外,this.props.code 是否正确传递给函数?

非常感谢。

【问题讨论】:

    标签: javascript reactjs react-context


    【解决方案1】:

    你可以按照这个:

    我的小提琴:https://jsfiddle.net/leolima/ds0o91xa/1/

    class Parent extends React.Component {
        	
         	sayHey(son) {
          	alert('Hi father, this is son '+son+' speaking');
          }
        	
          render() {
          	const children = React.Children.map(this.props.children, (child, index) => {
              return React.cloneElement(child, {
                someFunction: () => this.sayHey(index)
              });
            });
          
            return (<div>
              <b>Parent</b>
              <hr />
              {children}
            </div>);
          }
        }
        
        class Child extends React.Component {
          render() {
            return <div>
              <button onClick={() => this.props.someFunction()}>Child</button>
            </div>;
          }
        }
        
        ReactDOM.render(
        	<Parent>
        	  <Child />
        	  <Child />
        	</Parent>,
          document.getElementById('container')
        );
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
    <div id="container">
    </div>

    【讨论】:

      【解决方案2】:

      由于未定义handleBtnClick,因此存在 linter 错误。它是另一个类的方法,而不是独立函数。

      它在上下文消费者函数的范围内不可用。如果消费者应该更新上下文,更新函数应该是上下文的一部分:

      <MyContext.Provider value={{
          state: this.state,
          update: this.handleBtnClick
      }}>
      

      并像这样使用:

      context.update(this.props.code)
      

      【讨论】:

      • 非常感谢,它的工作就像一个魅力!我以为这是一个范围错误,但我不知道如何修复它......
      • 是否需要将值声明为变量才能avoid unintentional renders
      • @IanDunn 可能是这样。在通过 props 影响重新渲染的性能敏感的地方,坚持常规优化。对于 hooks API,这些将是非标量常量的常量值和组件范围内的变量的 useMemo。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-17
      • 2020-01-29
      • 2023-02-21
      • 2019-06-03
      • 1970-01-01
      相关资源
      最近更新 更多