Reactjs TypeError:this.setState不是函数,在Redux操作文件中

Reactjs TypeError:this.setState不是函数,在Redux操作文件中,reactjs,redux,react-redux,Reactjs,Redux,React Redux,我正在尝试将PixaBay克隆应用程序重新配置为Redux。当用户键入搜索文本时,应用程序检索照片。但是,当我在输入中键入时,它会立即中断。 根据我的研究,你只能在一个类中调用setState,所以我给了fetchPhotos一个箭头函数,但那不起作用。我还试图.bind(this),但这给了我一个解析错误。有人能告诉我我做错了什么吗?下面是以下错误以及我的代码 错误 TypeError: this.setState is not a function fetchPhotos src/actio

我正在尝试将PixaBay克隆应用程序重新配置为Redux。当用户键入搜索文本时,应用程序检索照片。但是,当我在输入中键入时,它会立即中断。 根据我的研究,你只能在一个类中调用setState,所以我给了fetchPhotos一个箭头函数,但那不起作用。我还试图
.bind(this)
,但这给了我一个解析错误。有人能告诉我我做错了什么吗?下面是以下错误以及我的代码

错误

TypeError: this.setState is not a function
fetchPhotos
src/actions/actions.js:10
   7 | 
   8 | export function fetchPhotos(e) {
   9 |   const url = `${ROOT_URL}/?key=${API_KEY}&q=${searchText}&image_type=photo`;
> 10 |   const request = this.setState({searchText: e.target.value}, () => {
  11 |     axios.get(url)
  12 |     .then(response => {
  13 |       this.setState({images: response.data.hits});

fetchPhotos
    node_modules/redux/es/redux.js:475
    Search._this.FetchPhotosHandler [as onChange]
    src/components/search/Search.js:11
       8 | class Search extends Component {
       9 | 
      10 |   FetchPhotosHandler = (e) => {
    > 11 |     this.props.fetchPhotos(e);
      12 |   }
      13 | 
      14 |   render() {
搜索容器

import React, { Component } from 'react';
import { fetchPhotos } from '../../actions/actions';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import TextField from 'material-ui/TextField';
import ImageResults from '../imageResults/ImageResults';

class Search extends Component {
  state = {
    searchText: '',
    images: []
  }

  FetchPhotosHandler = (e) => {
    this.props.fetchPhotos(e);
  }

  render() {
    return (
      <div>
        <TextField 
        name="searchText"
        value={this.props.searchText}
        onChange={this.FetchPhotosHandler}
        floatingLabelText="Search for photos"
        fullWidth={true} />
        <br />
        <ImageResults images={this.props.images} />
      </div>
    );
  }
}

function mapDispatchToProps(dispatch) {
  return bindActionCreators({ fetchPhotos, dispatch});
}

export default connect(null, mapDispatchToProps)(Search);
减速器

import { FETCH_PHOTOS } from '../actions/actions';

 const initialState = {
   searchText: '',
   images: []
 }


const reducer = (state = initialState, action) => {
  switch(action.type) {
    case FETCH_PHOTOS:
      return {
        ...state,
        images: action.data.hits
      };
    default: 
      return state;
  }
}

export default reducer;

您可以将组件类实例绑定到您的操作,它应该可以工作

FetchPhotosHandler = (e) => {
    this.props.fetchPhotos.bind(this)(e);
}

由于您已经从不同的模块导出了fetchPhotos,为了在那里执行setState,您需要将此上下文作为参数传递给fetchPhotos,并使用该参数执行setState。这就是该上下文的可用性

将此作为参数传递给fetchPhotos

FetchPhotosHandler = (e) => {
    this.props.fetchPhotos(e, this);
  }
在这里访问这个并进行seState

export function fetchPhotos(e, this) {
  const url = `${ROOT_URL}/?key=${API_KEY}&q=${searchText}&image_type=photo`;
  const request = this.setState({searchText: e.target.value}, () => {
    axios.get(url)
    .then(response => {
      this.setState({images: response.data.hits});
    })
    .catch(error => {
      console.log(error)
    });
  });

  return {
    type: FETCH_PHOTOS,
    payload: request 
  };
}

您应该避免尝试在操作中使用
setState()
,因为这完全不利于Redux
setState()
用于管理
React.Component
local。当您尝试使用Redux时,您应该从动作创建者处分派动作,这些动作通过还原器更新存储,最后通过
connect()
将存储值映射到组件的道具。下面是与Redux示例类似的代码重构示例

而不是尝试在操作中调用
setState()
,而是调度一个包含映像负载的操作。
Search
组件利用(connect()的第一个参数)将存储属性(如图像数组)映射到组件的道具。这些道具用于呈现数据列表。这完全消除了在
Search
上使用
images
本地状态属性的需要,因为在通过操作/还原器进行更改时,将从存储中检索值。这个例子使用中间件来处理异步操作,但是还有很多其他的选项可以考虑。 商店:

import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from './reducers';

const middleware = [ thunk ];

const store = createStore(
  rootReducer,
  applyMiddleware(...middleware)
);

export default store;
行动:

export const FETCH_PHOTOS = 'FETCH_PHOTOS';
export const RECEIVE_PHOTOS = 'RECEIVE_PHOTOS';

// fake data
const testPhotos = [
  { id: 1, src: 'https://placehold.it/250' },
  { id: 2, src: 'https://placehold.it/250' }
];

// fake API call as promise
const getTestPhotos = () => {
  return new Promise((resolve) => {
    setTimeout(() => {
      return resolve(testPhotos);
    }, 500);
  });
}

const fetchPhotos = (searchText) => ({
  type: FETCH_PHOTOS
});

const receivePhotos = (photos) => ({
  type: RECEIVE_PHOTOS,
  data: {
    hits: photos
  }
});

export const searchPhotos = (searchText) => dispatch => {
  // dispatch an action to handle loading/waiting for API response
  dispatch(fetchPhotos(searchText));

  // dispatch another action with payload within then()
  return getTestPhotos()
    .then(photos => dispatch(receivePhotos(photos)));
}
减速器:

import { FETCH_PHOTOS, RECEIVE_PHOTOS } from '../actions';

 const initialState = {
   loading: false,
   searchText: '',
   images: []
 }

const photos = (state = initialState, action) => {
  switch(action.type) {
    case FETCH_PHOTOS:
      return {
        ...state,
        loading: true
      };
    case RECEIVE_PHOTOS:
      return {
        ...state,
        loading: false,
        images: action.data.hits
      };
    default: 
      return state;
  }
}

export default photos;
搜索:

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { searchPhotos } from './actions';

class Search extends Component {
  constructor(props) {
    super(props);

    this.state = {
      searchText: ''
    };

    this.fetchPhotosHandler = this.fetchPhotosHandler.bind(this);
  }

  fetchPhotosHandler(e) {
    const { value: searchText } = e.target;

    this.setState({ ...this.state, searchText }, () => {
      this.props.dispatch(searchPhotos(e));
    })
  }

  render() {
    const { loading, images } = this.props;

    return (
      <div>
        <h1>Search</h1>
        <div>
          <label htmlFor="search">Search:</label>
          <input name="search" id="search" type="text" value={this.state.searchText} onChange={this.fetchPhotosHandler} />
        </div>

        {loading ? (
          <div>Loading...</div>
        ) : (
            <ul>
              {images.map(image => <li key={image.id}>{image.src}</li>)}
            </ul>
          )}
      </div>
    );
  }
}

const mapStateToProps = ({ photos: { loading, images } }) => ({ loading, images });

export default connect(mapStateToProps)(Search);
import React,{Component}来自'React';
从'react redux'导入{connect};
从“./actions”导入{searchPhotos};
类搜索扩展组件{
建造师(道具){
超级(道具);
此.state={
搜索文本:“”
};
this.fetchphotoHandler=this.fetchphotoHandler.bind(this);
}
抓取处理程序(e){
const{value:searchText}=e.target;
this.setState({…this.state,searchText},()=>{
此.props.dispatch(searchPhotos(e));
})
}
render(){
const{loading,images}=this.props;
返回(
搜寻
搜索:
{加载(
加载。。。
) : (
    {images.map(image=>
  • {image.src}
  • )}
)} ); } } const-mapStateToProps=({photos:{loading,images}})=>({loading,images}); 导出默认连接(MapStateTops)(搜索);
我创建了一个用于在基本级别上显示此功能的


希望这有帮助

你根本不应该,#39;不要在Redux操作中调用setState。setState用于管理
React.Component
的本地状态。操作的要点是将类型/有效负载分配给一个reducer,您可以使用它更新存储状态。该状态映射到组件中的道具。您可以使用中间件从API调用的then/catch中分派操作。看看像redux thunk这样的最小值。另外,您是否计划将存储状态映射到props(connect的第一个参数)以从存储中检索值?感谢您在@AlexanderStaroselsky上清除了这一点。我将重新考虑这一点。
setState
操作内部。这对我来说是第一次。别这样。setState()计划对组件的状态对象进行更新。您的代码需要进行重大重构。你甚至没有一个文件中的状态,那么你实际设置的是什么呢?我建议去拜访官员。。。快乐黑客;)谢谢你@很抱歉,这给了我一个类型错误:dispatch不是一个函数对不起,这给了我一个解析错误:意外的标记当然,给你。总共有3个<代码>未捕获错误:模块构建失败(来自./node_modules/babel loader/lib/index.js):SyntaxError:/Users/kennpangilian/DEV/ReactJS/flickr/src/actions/actions.js:意外标记•••
/src/actions/actions.js第8行:解析错误:意外标记
索引.js:1455./src/actions/actions.js SyntaxError:/Users/kennpangilian/DEV/ReactJS/flickr/src/actions/actions/actions.js:意外标记••
index.js:1455./src/actions/actions.js第8行:解析错误:意外令牌
非常感谢!这很有帮助!
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { searchPhotos } from './actions';

class Search extends Component {
  constructor(props) {
    super(props);

    this.state = {
      searchText: ''
    };

    this.fetchPhotosHandler = this.fetchPhotosHandler.bind(this);
  }

  fetchPhotosHandler(e) {
    const { value: searchText } = e.target;

    this.setState({ ...this.state, searchText }, () => {
      this.props.dispatch(searchPhotos(e));
    })
  }

  render() {
    const { loading, images } = this.props;

    return (
      <div>
        <h1>Search</h1>
        <div>
          <label htmlFor="search">Search:</label>
          <input name="search" id="search" type="text" value={this.state.searchText} onChange={this.fetchPhotosHandler} />
        </div>

        {loading ? (
          <div>Loading...</div>
        ) : (
            <ul>
              {images.map(image => <li key={image.id}>{image.src}</li>)}
            </ul>
          )}
      </div>
    );
  }
}

const mapStateToProps = ({ photos: { loading, images } }) => ({ loading, images });

export default connect(mapStateToProps)(Search);