【发布时间】:2020-08-11 23:20:33
【问题描述】:
我的 useEffect 函数在第一页加载时不会触发 redux 操作调用,我只是收到一个错误,上面写着 TypeError: Cannot read property 'length' of undefined 这可能是因为状态尚未加载,因为我猜该操作从未被触发。但是当我重新加载页面时,它工作正常,组件也加载没有任何问题。
这是我的反应组件:
const BooksById = ({bookdetails:{bookDetails,loading},getBookById,match}) =>{
useEffect(()=>{
console.log("action fired")
getBookById(match.params.genre)
},[getBookById,match.params.genre])
const [modal, setModal] = useState(false);
const toggle = () => setModal(!modal);
const [formData, setFormData] = useState({
status: '',
rating: '',
review: ''
});
const {status, rating, review} = formData;
const onChange = e => setFormData({...formData, [e.target.name]:e.target.value})
const onSubmit = e => {
e.preventDefault();
console.log(status, rating, review);
};
return (
(
<Fragment>
{loading ? (
<Spinner />
) : (
<Fragment>
<Container style={{paddingTop: "1.5rem"}}>
<Card>
<Row>
<aside className="col-sm-3 border-right">
<article className="gallery-wrap">
<div className="img-wrap">
<center>
<Media src="https://via.placeholder.com/190x320"/>
</center>
</div>
<center>
<Button color="primary" onClick={toggle}><i class="fa fa-book"></i> Add to shelf </Button>
<Modal isOpen={modal} toggle={toggle}>
<ModalHeader toggle={toggle}>Add to shelf</ModalHeader>
<ModalBody>
<Form onSubmit={e => onSubmit(e)}>
<FormGroup row>
<Label for="exampleSelect" sm={2}>Status</Label>
<Col sm={6}>
<Input type="select" name="Add to" id="exampleSelect" placeholder="* select a shelf" value={status} onChange={e => onChange(e)} required>
<option value=''></option>
<option value='plan to read'>plan to read</option>
<option value='reading'>reading</option>
<option value='completed'>completed</option>
<option value='dropped'>dropped</option>
</Input>
</Col>
</FormGroup>
<FormGroup row>
<Label for="exampleSelect" sm={2}>Rating</Label>
<Col sm={4}>
<Input type="select" name="rating" placeholder="(optional)" id="exampleSelect" value={rating} onChange={e => onChange(e)}>
<option value =''>(optional)</option>
<option value ='1'>1</option>
<option value ='2'>2</option>
<option value ='3'>3</option>
<option value ='4'>4</option>
<option value ='5'>5</option>
</Input>
</Col>
</FormGroup>
<FormGroup row>
<Label for="exampleText" sm={2}>Review</Label>
<Col sm={9}>
<Input type="textarea" name="review" placeholder="(optional)" id="exampleText" value={review} onChange={e => onChange(e)} />
</Col>
</FormGroup>
<Button type ="submit" color="primary" >save</Button>{' '}
<Button color="secondary" onClick={toggle}>Cancel</Button>
</Form>
</ModalBody>
</Modal>
</center>
</article>
</aside>
<aside class="col-sm-7">
<article class="card-body p-5">
<h3 class="title mb-3">{bookDetails.bookName}</h3>
<dl class="param param-feature">
<dt>Rating</dt>
<dd>
<span class="float-center"><i class="text-warning fa fa-star"></i></span>
<span class="float-center"><i class="text-warning fa fa-star"></i></span>
<span class="float-center"><i class="text-warning fa fa-star"></i></span>
{' '}3.05
</dd>
</dl>
<dl class="item-property">
<dt>Description</dt>
<dd><p>{bookDetails.bookDescription}</p></dd>
</dl>
<dl class="param param-feature">
<dt>Author</dt>
<dd>someone</dd>
</dl>
<dl class="param param-feature">
<dt>Publish date</dt>
<dd>some date</dd>
</dl>
<dl class="param param-feature">
<dt>Genres</dt>
<dd>{
bookDetails.bookGenre.map(x=>x + ', ')}</dd>
</dl>
</article>
</aside>
</Row>
</Card>
</Container>
{/* review container */}
<Container style={{paddingTop: "1.5rem",paddingBottom: "1.5rem"}}>
<hr/>
<h2 style={{paddingTop: "1.5rem",paddingBottom: "1.5rem"}}>Reviews</h2>
<Card>
<CardBody>
<Row>
<Col md="12">
<p>
<strong>some one</strong>
<span class="float-right"><i class="text-warning fa fa-star"></i></span>
<span class="float-right"><i class="text-warning fa fa-star"></i></span>
<span class="float-right"><i class="text-warning fa fa-star"></i></span>
</p>
<div class="clearfix"></div>
<p>Lorem Ipsum is simply dummy text of the pr make but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
</Col>
</Row>
</CardBody>
</Card>
</Container>
</Fragment> )}
</Fragment>
)
)
BooksById.propTypes={
bookdetails: PropTypes.object.isRequired,
getBookById: PropTypes.func.isRequired
}
const mapStateToProps = state => ({
bookdetails: state.bookdetails
})
export default connect(mapStateToProps,{getBookById}) (BooksById);
这是我要调用的操作:
export const getBookById = (id) => dispatch => {
axios.get(`/api/booksDetails/${id}`)
.then(res=>{
dispatch({
type: GET_BOOKBYID,
payload: res.data
})
})
.catch(err=>{
dispatch({
type: BOOKDETAILS_FAIL,
payload: { msg: err.response.statusText, status: err.response.status }
})
})
}
这里是减速器:
export default function (state = initialState, action) {
const { type, payload } = action;
switch (type) {
case GET_BOOKDETAILS:
case GET_BOOKBYGENRE:
return{
...state,
loading: false,
bookDetails: payload
}
case GET_BOOKBYID:
return{
...state,
loading: false,
bookDetails: payload
}
case BOOKDETAILS_FAIL:
return{
...state,
loading: false,
bookDetails: payload
}
default:
return state;
}
}
请帮我改一下,谢谢。
【问题讨论】:
-
错误是
TypeError: Cannot read property 'length' of undefined,但您发布的代码没有尝试从任何地方获取length。也许在获取 bookDetails.length 之前尝试将初始状态的 bookDetails 设置为数组或正确使用loading(我想这就是你想要做的,但缺少代码)。通常你会检查 redux 开发工具,看看是否使用正确的值调度了正确的操作,以及它们是否会导致正确的更改。 -
@HMR 我现在已经上传了代码,实际上文件太大了所以我没有上传它,而且我正在使用 redux devtools 并且在我重新加载之前操作根本不会触发该页面,如果加载错误,我还添加了一个微调器,但它仍然无法正常工作
-
仍然没有看到导致错误的行。 Redux devtools 应该在调度 init 操作时向您显示状态,以便您可以确保正确设置加载并且您没有将加载映射到连接中的道具。
标签: reactjs redux react-redux