Reactjs TypeError:this.setState不是函数,在Redux操作文件中
我正在尝试将PixaBay克隆应用程序重新配置为Redux。当用户键入搜索文本时,应用程序检索照片。但是,当我在输入中键入时,它会立即中断。 根据我的研究,你只能在一个类中调用setState,所以我给了fetchPhotos一个箭头函数,但那不起作用。我还试图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
.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()
,因为这完全不利于ReduxsetState()
用于管理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);