简体   繁体   English

React Context with Hooks 总是“落后一步”

[英]React Context with Hooks is always "one step behind"

I am coding a computer comparison website and I encountered an issue when setting filters for the API call.我正在编写一个计算机比较网站,但在为 API 调用设置过滤器时遇到了问题。 It seems to always be "one step behind" when I add a filter.当我添加过滤器时,它似乎总是“落后一步”。 For example, I add the filter for "orderby" and then call getComputers() , which fetches the pcs from our api using the filters as parameters, but it doesn't apply any parameters, as the filters are still empty.例如,我为“orderby”添加过滤器,然后调用getComputers() ,它使用过滤器作为参数从我们的 api 获取 pc,但它不应用任何参数,因为过滤器仍然是空的。 If I do it again with a different value for "orderby" it takes the value from before as param for the api call.如果我使用不同的“orderby”值再次执行此操作,则它将之前的值作为 api 调用的参数。 I don't understand why this works the way it does and would really appreciate any help :)我不明白为什么它会这样工作,并且非常感谢任何帮助:)

Yes, I did research on this before, but nothing seemed to work for me...是的,我之前做过这方面的研究,但似乎没有什么对我有用......

Here is my code:这是我的代码:

The search results page:搜索结果页面:

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;

Strangely, my page displays the current "orderby" filter correctly in the little pills (see line 42).奇怪的是,我的页面在小药丸中正确显示了当前的“orderby”过滤器(参见第 42 行)。 But the API call doesn't take the right filter...但是 API 调用没有采用正确的过滤器...

Relevant parts of my Context:我的上下文的相关部分:

SearchState.js:搜索状态.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: 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
      };
};

I am really struggling with this right now and hope to find some help here.我现在真的很挣扎,希望能在这里找到一些帮助。 Big thanks in advance!非常感谢提前! You people on here are great :)你们这里的人很棒:)

getComputers works on other state "instance"/ref` getComputers适用于其他state “实例”/ref`

You can use useEffect as addFilter changes filter :您可以使用useEffect作为addFilter更改filter

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

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

addFilter changes filter ... filter change runs effect code (every time it changes) addFilter更改filter ... filter更改运行效果代码(每次更改时)

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

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