繁体   English   中英

React 上下文状态共享在同级组件中不起作用

[英]React context state sharing not working in sibling components

我有一个简单的 ToDo 应用程序,其中包含一些组件。 我想要做的就是共享状态和更新上下文数据。 我可以用 props 来做,但将来,如果我有更多的组件,那么用 props 传递数据会太麻烦。 这是我的代码...

主上下文.js

import React, { createContext, useState } from "react";

const MainContext = createContext([{}, () => {}]);

const MainContextProvider = (props) => {
  const [state, setState] = useState({ title: "", body: "" });
  return (
    <MainContext.Provider value={[state, setState]}>
      {props.children}
    </MainContext.Provider>
  );
};

export { MainContext, MainContextProvider };

应用程序.js

import MainContent from "./MainContent";
import { MainContextProvider } from "./MainContext";
export default class App extends Component {
  constructor() {
    super();
    this.state = {
    };
  }
  render() {
    return (
      <div className="container">
        <MainContextProvider>
          <Nav navigationItems={this.state.navItems} />
          <MainContent />
          <Footer />
        </MainContextProvider>
      </div>
    );
  }
}

主要内容.js

import React, { Component } from "react";
import CardType from "./CardType";
import FormData from "./FormData";

class MainContent extends Component {
  constructor(props) {
    super(props);
    this.state = {
      isLoading: true,
      initialCounter: 0,
      endCounter: 10,
      showLoadMore: true,
      cards: [],
    };
  }

  DeleteCard = (cardId) => {
    console.log(cardId);
    this.setState((prevState) => {
      const newCardArray = prevState.cards.filter((card) => card.id !== cardId);
      return {
        cards: newCardArray,
      };
    });
  };

  AddCard = (formData) => {
    this.setState((prevState) => {
      const newCardData = {
        id: prevState.cards[prevState.cards.length - 1].id + 1,
        userId: 12,
        title: formData.title,
        body: formData.description,
      };

      return {
        cards: [...prevState.cards, newCardData],
        // update the number of posts to +1
        endCounter: prevState.endCounter + 1,
      };
    });
  };
  componentDidMount() {
    fetch("https://jsonplaceholder.typicode.com/posts")
      .then((response) => response.json())
      .then((json) => {
        this.setState({ isLoading: false, cards: json });
      });
  }

  render() {
    if (this.state.isLoading) {
      return <h1>Loading....</h1>;
    } else {
      const cardsShow = this.state.cards.map((card) => {
        return (
          <CardType
            key={card.id}
            cardData={card}
            deleteCard={this.DeleteCard}
          />
        );
      });

      return (
        <main className="jumbotron">
          <h1>ToDo</h1>
          <FormData data={this.AddCard} />
          {cardsShow
            .reverse()
            .slice(this.state.initialCounter, this.state.endCounter)}
          {this.state.showLoadMore ? (
            <button
              onClick={() => {
                this.setState((prevState) => {
                  const newEndCounter = prevState.endCounter + 10;
                  const showLoadButton =
                    prevState.cards.length > newEndCounter ? true : false;

                  return {
                    endCounter: newEndCounter,
                    showLoadMore: showLoadButton,
                    // initialCounter: prevState.initialCounter + 10,
                  };
                });
              }}
            >
              Load More
            </button>
          ) : null}
        </main>
      );
    }
  }
}

export default MainContent;

卡片类型.js

import React, { useContext, useEffect } from "react";
import { MainContextProvider } from "./MainContext";

const CardType = (props) => {
  const [formData, setFormData] = useContext(MainContext);
  const updateValues = (card) => {
    setFormData(() => {
     return {
        title: card.title,
        body: card.body,
      };
    });
  };
  return (
    <div className="card">
      <div className="card-body">
        <h1>{props.cardData.title}</h1>
        <p className="card-text">{props.cardData.body}</p>
        <button onClick={() => props.deleteCard(props.cardData.id)}>
          Delete
        </button>
        <button onClick={() => updateValues(props.cardData)}>Update</button>
      </div>
    </div>
  );
};

export default CardType;

表单数据.js

import React, { useState, useContext } from "react";
import { MainContextProvider } from "./MainContext";

const FormData = (props) => {
  const [formData, setFormData] = useContext(MainContext);
  const [title, setTitle] = useState(formData.title);
  const [description, setDescription] = useState("formData.body);

  const handleSubmit = (e) => {
    e.preventDefault();
    props.data({ title: title, description: description });
    setTitle("");
    setDescription("");
  };

  return (
    <form>
      <div className="form-group">
        <label>Name</label>
        <input
          className="col-sm-12"
          type="text"
          value={title}
          onChange={(e) => setTitle(e.target.value)}
        />
      </div>
      <div className="form-group">
        <label>Description</label>
        <textarea
          className="col-sm-12"
          name="cardDescription"
          value={description}
          onChange={(e) => {
            setDescription(e.target.value);
          }}
        />
      </div>

      <p>{description}</p>
      <button onClick={(e) => handleSubmit(e)}>Add</button>
    </form>
  );
};

export default FormData;

我想要的是,当我点击每个待办事项的更新按钮时,我的表单应该填充选定的待办事项数据并更新上下文并在保存时将我的上下文更新回空字符串。 我是 React 的新手。 请分享是否有任何其他替代方法可以在不使用上下文的情况下执行此操作。

来自useContext文档:

不要忘记 useContext 的参数必须是上下文对象本身:

  • 正确: useContext(MyContext)
  • 不正确: useContext(MyContext.Consumer)
  • 不正确: useContext(MyContext.Provider)

所以在你的代码示例中,替换这一行

const [formData, setFormData] = useContext(MainContextProvider);

const [formData, setFormData] = useContext(MainContext);

为了防止将来出现类似错误,您可以创建一个包装器钩子来访问上下文。

MainContext.js 中

const useMainContext = () => useContext(MainContext)

现在你可以在任何像这样的功能组件中使用它们

const [formData, setFormData] = useMainContext();

现场演示

编辑 React - UseContext

暂无
暂无

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM