Переменная состояния не меняется из контекста - PullRequest
0 голосов
/ 11 февраля 2020

Я, должно быть, неправильно настраиваю свой контекст или состояние Но по какой-то причине я не могу изменить свое состояние showDetails. Предполагается показать скрытый столбец, когда он изменится на true, условно добавив bootstrap class d-none. У меня есть событие click в моем компоненте Order, которое работает setShowDetails(true), и оно не работает. Другие элементы этой функции выполняются.

Соответствующий код из моего компонента Order:

const Order = props => {
  const { orderID } = props;
  const { setShowDetails } = useScheduleActionsContext();

  // show the details section when user clicks an order
  const showDetails = orderID => {
    console.log("showDetails function!");
    // needed to fix an issue with doubled borders between the columns
    document.querySelector(".lines .col.last").style.borderRightWidth = "0px";
    setShowDetails(true);
  };

  return (
    <MyOrder className={"order"} onClick={e => showDetails(orderID, e)}>
      <div className={"orderID"}>{orderID}</div>
      <h3>Order</h3>
    </MyOrder>
  );
};

Тогда мой компонент DetailsColumn содержит это:

const { showDetails } = useScheduleContext();
  const { setShowDetails } = useScheduleActionsContext();

  // determine whether to show the details section based on the passed
  // in prop showDetails
  const className =
    "col details-column text-center" + (showDetails ? "" : " d-none");

Здесь весь мой контекстный файл:

import React, {
  createContext,
  useContext,
  useEffect,
  useState,
  useMemo
} from "react";
import { useGlobalSpinnerActionsContext } from "./GlobalSpinnerContext";
import PropTypes from "prop-types";

// export const ScheduleContext = createContext({
//   title: "My title"
// });

const pageTitle = "My Title";

const initialValues = {
  title: pageTitle,
  filteredOrders: [],
  columns: []
};

const ScheduleContext = createContext(initialValues);
const ScheduleActionsContext = createContext({});

export const useScheduleContext = () => useContext(ScheduleContext);
export const useScheduleActionsContext = () =>
  useContext(ScheduleActionsContext);

export const ScheduleProvider2 = props => {
  const setGlobalSpinner = useGlobalSpinnerActionsContext();
  setGlobalSpinner(true);
  console.log(setGlobalSpinner);

  const [context, setContext] = useState({});
  // eslint-disable-next-line no-unused-vars
  const [orders, setOrders] = useState([]);
  // eslint-disable-next-line no-unused-vars
  const [filteredOrders, setFilteredOrders] = useState([]);
  // eslint-disable-next-line no-unused-vars
  const [pendingOrderIDs, setPendingOrderIDs] = useState([]);
  const [lineType, setLineType] = useState(pageTitle);
  const [title, setTitle] = useState(pageTitle);
  const [columns, setColumns] = useState([]);
  const [showDetails, setShowDetails] = useState(false);

  useEffect(() => {
    setGlobalSpinner(true);
    console.log("we are running useEffect in context!!!");
    const fetchPendingOrders = async () => {
      const ordersURL = "https://randomuser.me/api";
      return await fetch(ordersURL, {
        cache: "no-cache", // *default, no-cache, reload, force-cache, only-if-cached
        headers: {
          "Content-Type": "application/json"
        },
        referrerPolicy: "no-referrer" // no-referrer, *client
      });
    };
    fetchPendingOrders()
      .then(result => {
        return result.json();
      })
      .then(data => {
        const tempOrders = data.results.map((el, index) => {
          return {
            id: index,
            gender: el.gender
          };
        });
        console.log("tempOrders: ", tempOrders);
        setOrders(tempOrders);
        setFilteredOrders(tempOrders);
        const pendingOrderIDVals = tempOrders.map(function(val) {
          return val.id;
        });
        setPendingOrderIDs(pendingOrderIDVals);

        const contextValue = {
          orders: tempOrders,
          setOrders,
          showDetails,
          title,
          columns
        };
        setContext(contextValue);
        setGlobalSpinner(false);
        console.log(contextValue);
      })
      .catch(e => {
        console.log(e);
      });
  }, [setGlobalSpinner]);

  const actionsValues = useMemo(() => {
    return {
      setLineType,
      setColumns,
      setTitle,
      setShowDetails,
      setFilteredOrders,
      setPendingOrderIDs
    };
  }, []);

  return (
    <ScheduleContext.Provider value={context}>
      <ScheduleActionsContext.Provider value={actionsValues}>
        {props.children}
      </ScheduleActionsContext.Provider>
    </ScheduleContext.Provider>
  );
};

ScheduleProvider2.propTypes = {
  children: PropTypes.oneOfType([
    PropTypes.arrayOf(PropTypes.node),
    PropTypes.node
  ]).isRequired
};

Я также создал песочницу для кода, чтобы ее можно было протестировать и поиграть, а код можно настроить. Если вы щелкнете по одному из синих полей «Заказ», то должен отобразиться столбец «Детали заказа». https://codesandbox.io/s/romantic-lamarr-lb11g

Ответы [ 2 ]

1 голос
/ 12 февраля 2020

Хорошо, я выяснил, почему это не работает.

  1. Вы должны добавить showDetails: false к initialValues компонента ScheduleContext.
  2. Вы должны добавить showDetails в качестве зависимости к useEffect hook как:
useEffect(() => {
   ...
 }, [setGlobalSpinner, showDetails]);
0 голосов
/ 11 февраля 2020

Ваша переменная состояния изменяется правильно. У вас проблема с передачей компонента className in DetailsColumn.

...