带挂钩的React Context总是“落后一步”

时间:2020-03-27 15:14:30

标签: javascript reactjs state setstate

我正在编写一个计算机比较网站的代码,在为API调用设置过滤器时遇到问题。当添加过滤器时,似乎总是“落后一步”。例如,我为“ orderby”添加了过滤器,然后调用getComputers(),它使用过滤器作为参数从我们的api中获取了pc,但是由于过滤器仍然为空,因此它不应用任何参数。如果我使用“ orderby”的其他值再次执行此操作,则它将之前的值作为api调用的参数。我不明白为什么这样做会起作用,并且会非常感谢您的帮助:)

是的,我之前对此进行过研究,但似乎没有任何效果...

这是我的代码:

搜索结果页面:

import React from 'react';
import { useContext } from 'react';
import SearchContext from '../../context/search/SearchContext';
import Navbar from '../layout/Navbar';
import Computers from '../computer/Computers';
import Select from 'react-select';

const SearchResults = () => {
  const searchContext = useContext(SearchContext);
  const { filters, orders, getComputers, addFilter } = searchContext;

  return (
    <>
      <Navbar activeItem='Search'></Navbar>

      <div className='container my-3 text-dark'>
        <div className='row'>
          <div className='col-lg-9 col-md-6'>
            <h1 className='display-3 mt-3'>Suche</h1>
          </div>
          <div className='col-lg-3 col-md-6'>
            <Select
              placeholder='Sortierung'
              options={orders.map(order => {
                return { value: order.value, label: order.trans };
              })}
              onChange={val => {
                addFilter({ name: 'orderby', value: val.value });
                getComputers();
              }}
            />
          </div>
        </div>
        <div className='my-3'>
          {filters.map((filter, index) => {
            var text = filter.value.toString();
            return (
              <span
                className='badge badge-pill badge-secondary mx-1 p-2'
                key={index}
              >
                {text.charAt(0).toUpperCase() + text.slice(1)}
              </span>
            );
          })}
        </div>

        <Computers></Computers>
      </div>
    </>
  );
};

export default SearchResults;

奇怪的是,我的页面在小药丸中正确显示了当前的“ orderby”过滤器(请参见第42行)。但是API调用没有使用正确的过滤器...

我的上下文相关部分:

SearchState.js:

const [state, dispatch] = useReducer(SearchReducer, initialState);

// ACTIONS

  // Add filter
  const addFilter = filter => {
    console.log(state.filters);
    dispatch({ type: ADD_FILTER, payload: filter });
  };

// Get PCs from API
  const getComputers = async () => {
    try {
      state.loading = true;
      console.log(state.filters);
      let params = {};
      state.filters.forEach(filter => {
        // if (filter.name !== 'usecase' && filter.name !== 'type')
        //only as long as usecase and type are not implemented in api yet
        if (!params[filter.name]) params[filter.name] = '';
        params[filter.name] = filter.value;
      });
      console.log(params);
      const res = await axios.get(
        'notgonnatellumyurlxd',
        {
          params
        }
      );
      console.log(res);
      dispatch({ type: GET_COMPUTERS, payload: res.data });
    } catch (err) {
      console.log(err);
    }
  };

SearchReducer.js:

export default (state, action) => {
  switch (action.type) {
    case ADD_FILTER:
      // Used for deciding whether to update existing filter or set new
      var update = false;
      state.filters.forEach(filter => {
        if (filter.name === action.payload.name) {
          update = true;
        }
      });
      return {
        ...state,
        filters: !update
          ? [...state.filters, action.payload]
          : state.filters.map(filter =>
              filter.name === action.payload.name ? action.payload : filter
            )
      };
.
.
.
case GET_COMPUTERS:
      return {
        ...state,
        computers: action.payload,
        loading: false
      };
};

我现在真的很为此苦苦挣扎,希望能在这里找到一些帮助。预先感谢!你们这里的人很棒:)

1 个答案:

答案 0 :(得分:1)

getComputers适用于其他state个“实例” / ref`

您可以将useEffect用作addFilter的更改filter

useEffect(() => {
  getComputers();
}, [filter]);

onChange={val => addFilter({ name: 'orderby', value: val.value })}

addFilter的更改filter ... filter的更改会运行效果代码(每次更改时)