簡體   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