Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/407.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript TypeError:searchField.toLowerCase在使用redux时不是函数_Javascript_Reactjs_Redux_React Hooks - Fatal编程技术网

Javascript TypeError:searchField.toLowerCase在使用redux时不是函数

Javascript TypeError:searchField.toLowerCase在使用redux时不是函数,javascript,reactjs,redux,react-hooks,Javascript,Reactjs,Redux,React Hooks,为了更好地理解react,我一直在做一个小项目。我最近将它转换为使用钩子,并尝试用它实现redux。但是我现在得到了以下错误 TypeError: searchField.toLowerCase is not a function 查看文档时,我从react redux停止使用connect,转而使用useDispatch和useSelector。但我相信我已经正确地设置了一切,但不确定为什么会出现这个错误 这是我的action.js import { SEARCH_EVENT } from

为了更好地理解react,我一直在做一个小项目。我最近将它转换为使用钩子,并尝试用它实现redux。但是我现在得到了以下错误

TypeError: searchField.toLowerCase is not a function
查看文档时,我从
react redux
停止使用
connect
,转而使用
useDispatch
useSelector
。但我相信我已经正确地设置了一切,但不确定为什么会出现这个错误

这是我的action.js

import { SEARCH_EVENT } from './searchfield_constants';

export const setSearchField = (payload) => ({ type: SEARCH_EVENT, payload });
这是我的减速机

import { SEARCH_EVENT } from './searchfield_constants';

const initialState = {
  searchField: '',
};

export const searchRobots = (state = initialState, action = {}) => {
  switch (action.type) {
    case SEARCH_EVENT:
      return { ...state, searchField: action.payload };
    default:
      return state;
  }
};
这是我的index.js,我使用的是
提供者
from
react redux

import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { createStore } from 'redux';
import { searchRobots } from './searchfield/searchfield_reducers';
import './styles/index.css';
import App from './App';

const store = createStore(searchRobots);

ReactDOM.render(
  <React.StrictMode>
    <Provider store={store}>
      <App />
    </Provider>
  </React.StrictMode>,
  document.getElementById('root')
);
从“React”导入React;
从“react dom”导入react dom;
从'react redux'导入{Provider};
从“redux”导入{createStore};
从“./searchfield/searchfield_reducers”导入{searchRobots};
导入“./styles/index.css”;
从“./App”导入应用程序;
const store=createStore(searchRobots);
ReactDOM.render(
,
document.getElementById('root'))
);
最后是我的App.jsx

import { useState, useEffect, useCallback } from 'react';
import { setSearchField } from './searchfield/searchfield_actions';
import { useDispatch, useSelector } from 'react-redux';
import axios from 'axios';
import React from 'react';
import CardList from './components/CardList';
import SearchBox from './components/SearchBox';
import Scroll from './components/Scroll';
import Error from './components/Error';
import 'tachyons';
import './styles/App.css';

// const mapStateToProps = (state) => ({
//   searchField: state.searchField,
// });

// const mapDispatchToProps = (dispatch) => ({
//   onSearchChange: (e) => dispatch(setSearchField(e.target.value)),
// });

const App = () => {
  const searchField = useSelector(state => state.searchField)
  const dispatch = useDispatch();
  const [robots, setRobots] = useState([]);
  // const [searchField, setSearchField] = useState('');

  const fetchUsers = useCallback(async () => {
    try {
      const result = await axios('//jsonplaceholder.typicode.com/users');
      setRobots(result.data);
    } catch (error) {
      console.log(error);
    }
  }, []); // eslint-disable-line react-hooks/exhaustive-deps

  useEffect(() => {
    fetchUsers();
  }, []); // eslint-disable-line react-hooks/exhaustive-deps

  const filteredRobots = robots.filter((robot) => {
    return robot.name.toLowerCase().includes(searchField.toLowerCase());
  });

  return !robots.length ? (
    <h1 className='f1 tc'>Loading...</h1>
  ) : (
    <div className='App tc'>
      <h1 className='f1'>RoboFriends</h1>
      <SearchBox searchChange={dispatch(setSearchField(e => e.target.value))} />
      <Scroll>
        <Error>
          <CardList robots={filteredRobots} />
        </Error>
      </Scroll>
    </div>
  );
};


export default App;
从'react'导入{useState,useffect,useCallback};
从“/searchfield/searchfield_actions”导入{setSearchField};
从'react redux'导入{useDispatch,useSelector};
从“axios”导入axios;
从“React”导入React;
从“./components/CardList”导入卡片列表;
从“./components/SearchBox”导入SearchBox;
从“./components/Scroll”导入滚动;
从“./components/Error”导入错误;
输入‘超光速子’;
导入“./styles/App.css”;
//常量mapStateToProps=(状态)=>({
//searchField:state.searchField,
// });
//const mapDispatchToProps=(调度)=>({
//onSearchChange:(e)=>调度(设置搜索字段(e.target.value)),
// });
常量应用=()=>{
const searchField=useSelector(state=>state.searchField)
const dispatch=usedpatch();
const[robots,setRobots]=useState([]);
//常量[searchField,setSearchField]=useState(“”);
const fetchUsers=useCallback(异步()=>{
试一试{
const result=await axios('//jsonplaceholder.typicode.com/users');
setRobots(result.data);
}捕获(错误){
console.log(错误);
}
},[]);//eslint禁用行反应挂钩/deps
useffect(()=>{
fetchUsers();
},[]);//eslint禁用行反应挂钩/deps
常量过滤器机器人=机器人。过滤器((机器人)=>{
return robot.name.toLowerCase().includes(searchField.toLowerCase());
});
返回!机器人。长度(
加载。。。
) : (
机器人
e、 target.value)}/>
);
};
导出默认应用程序;

我做错了什么?

在你的App.js中,转换这一行

const searchField = useSelector(state => state.searchField)

基本上从
state.searchField

这归因于redux如何设置状态

在reducer
searchRobots
中,redux提供的初始状态为

state = {
...state, 
searchField
}
在这一行中
返回{…state,searchField:action.payload},您正在添加

另一个属性
searchField
设置为
状态。searchField
对象,因此您需要对其进行解构。

看起来您的
searchField
值被设置为未定义或某些非字符串值

我发现这行不正确

<SearchBox searchChange={dispatch(setSearchField(e => e.target.value))} />
e.target.value))}/>
应该改成

<SearchBox searchChange={() => dispatch(setSearchField(e => e.target.value))} />
dispatch(setSearchField(e=>e.target.value))}/>
以便在搜索更改时可以调用此函数。当前您正在直接调用dispatch,这可能会将您的
搜索字段设置为未定义


同样为了安全起见,在使用
toLowerCase()
之前,将其转换为字符串ie
searchField.toString().toLowerCase()
,因此解决方案如下:

我创建了一个名为searchChange的函数,它调用dispatch,然后调用setSearchField,它使用e.target.value作为有效负载

  const onSearchChange = (e) => {
    dispatch(setSearchField(e.target.value));
  };
因此,最终返回结果如下所示

return !robots.length ? (
    <h1 className='f1 tc'>Loading...</h1>
  ) : (
    <div className='App tc'>
      <h1 className='f1'>RoboFriends</h1>
      <SearchBox searchChange={onSearchChange} />
      <Scroll>
        <Error>
          <CardList robots={filteredRobots} />
        </Error>
      </Scroll>
    </div>
  );
};
返回!机器人。长度?(
加载。。。
) : (
机器人
);
};
return !robots.length ? (
    <h1 className='f1 tc'>Loading...</h1>
  ) : (
    <div className='App tc'>
      <h1 className='f1'>RoboFriends</h1>
      <SearchBox searchChange={onSearchChange} />
      <Scroll>
        <Error>
          <CardList robots={filteredRobots} />
        </Error>
      </Scroll>
    </div>
  );
};