ReactJS-从数据库获取数据并从.then返回承诺结果,然后返回return函数

时间:2020-02-04 21:30:12

标签: javascript reactjs promise

TLDR; 基本上,我试图弄清楚如何将api上的数据加载到我的React应用程序中,以便我的应用程序立即可用。如果需要,我可以完全重做或修改下面的任何或所有代码。我只需要弄清楚该怎么做。我认为它需要进入上下文,以便我所有的组件都可以访问它。

我用硬编码的伪数据创建了一个ReactJS应用程序,它运行良好。现在,我们需要将其转换为从数据库中提取真实的动态数据,并且在理解promise如何与state和useEffect配合使用时遇到麻烦。变得如此混乱。我将在最后的.then调用中创建contextValue对象,并且需要在return的文件末尾使用该对象。我尝试将其保存到状态变量,但这似乎不起作用。我在另一个文件中收到错误TypeError: _useContext is null

这是整个上下文文件,其中删除了所有不相关的代码:

import PropTypes from 'prop-types';

export const ScheduleContext = createContext();

export const ScheduleProvider2 = (props) => {
    const allChemicals = [...];

    const allBOMs = [...];

    const makeRandomStr = (length) => {...};

    const getRandomChemicals = () => {};

    const getRandomBOMs = () => {..};

    const getRandomIntInclusive = (min, max) => {...};

    const randomDate = (start, end, startHour, endHour) => {...};

    const quotes = [...];

    const getRandomComments = () => {..};

    const getBatchNumbers = () => {...};

    const [context, setContext] = useState(null);
    const [orders, setOrders] = useState(null);
    const [filteredOrders, setFilteredOrders] = useState(null);
    const [pendingOrderIDs, setPendingOrderIDs] = useState(null);
    const [activeOrder, setActiveOrder] = useState(0);
    const [columns, setColumns] = useState([]);
    const [showDetails, setShowDetails] = useState(false);
    const [title, setTitle] = useState('Title');
    const [lineType, setLineType] = useState('Type');
    const chemicals = useState(allChemicals);
    const BOMs = useState(allBOMs);

    useEffect(() => {
        const fetchPendingOrders = () => {
            const ordersURL = 'http://localhost:3001/orders';
            return 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.map((el, index) => {
                    return {
                        id: index,
                        .....
                    };
                });

                setOrders(tempOrders);
                setFilteredOrders(tempOrders);
                const pendingOrderIDVals = tempOrders.map(function(val) {
                    return val.id;
                });
                setPendingOrderIDs(pendingOrderIDVals);

                const contextValue = {
                    orders,
                    setOrders,
                    filteredOrders,
                    setFilteredOrders,
                    pendingOrderIDs,
                    setPendingOrderIDs,
                    columns,
                    setColumns,
                    showDetails,
                    setShowDetails,
                    activeOrder,
                    setActiveOrder,
                    title,
                    setTitle,
                    lineType,
                    setLineType,
                    chemicals,
                    BOMs
                };
                setContext(contextValue);

                console.log(contextValue);
            })
            .catch((e) => {
                console.log(e);
            });
    }, []);



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

该错误TypeError: _useContext is null发生在读取上下文文件的文件的功能组件中。这是两个相关的行(这是发生错误的SchedulePage.js的开头):

import { ScheduleContext } from '../../schedule-context-new';

const Schedule = () => {
const {
        showDetails,
        orders,
        setOrders,
        activeOrder,
        columns,
        setColumns,
        title,
        pendingOrderIDs,
        filteredOrders,
        setTitle,
        lineType,
        setLineType
    } = useContext(ScheduleContext);
....

如果这有所作为,我也在app.js中使用ScheduleProvider:

import { ScheduleProvider2 } from './schedule-context-new';
import Schedule from './components/home/SchedulePage';
import './App.scss';

const App = () => {
    return (
        <ScheduleProvider2>
            <div className={'App'}>
                <Schedule />
            </div>
        </ScheduleProvider2>
    );
};

更新: 通过示例链接,我尝试将上下文文件的末尾更改为此,现在它抱怨Error: ScheduleProvider2(...): Nothing was returned from render.

(async function() {
        const context = await fetchPendingOrders();

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

更新2 -我已经弄清楚了如何为我的应用创建一个基本准系统副本,该副本实际上会产生相同的错误。再次由于某种原因,直到我将useEffect注释掉之后,useEffect代码才被调用,我不知道为什么。 https://codesandbox.io/s/tender-cookies-jzn5v

1 个答案:

答案 0 :(得分:4)

您应该等待API结果

const Schedule = () => {
  const {
    orders,
    setOrders,
    filteredOrders,
    setFilteredOrders,
    pendingOrderIDs,
    setPendingOrderIDs
  } = useContext(ScheduleContext) ||[];

或使用useEffect

const data = useContext(ScheduleContext);

useEffect(() => {
  // Do you calculation here when ScheduleContext is ready
}, [data])

codesandbox