问题描述
我正在使用MERN堆栈和Redux。我正在尝试为各种组件编写一些测试用例。对于任何连接的我都会收到错误消息...
“在“ Connect(Subject)”的上下文中找不到“存储”。要么将根组件包装在中,要么将自定义的React上下文提供程序传递给Connect(Subject),并将相应的React上下文使用者传递给Connect选项。”
我尝试将其包装在提供程序中,但仍然收到相同的消息。有人知道如何解决这个问题吗?
测试
import React from "react";
import { shallow } from "enzyme";
import { mount } from "enzyme";
import Provider from "react";
import { createStore,applyMiddleware } from "redux";
import Subject from "../components/layout/Subject";
import thunk from "redux-thunk";
import combineReducers from "../reducers/index";
const store = createStore(combineReducers,undefined,applyMiddleware(thunk));
it("Subject should render without errors",() => {
const component = mount(
<Provider store={store}>
<Subject />
</Provider>
);
const wrapper = component.find("#Subject");
expect(wrapper.length).toBe(1);
});
组件
import React,{ Component } from "react";
import PropTypes from "prop-types";
import GoogleSearch from "./GoogleSearch";
import { connect } from "react-redux";
import { fetchLatestSubjects } from "../../actions/subject";
import { fetchTopicSubjects } from "../../actions/subject";
import { fetchTopicComments } from "../../actions/comment";
import { fetchComments } from "../../actions/comment";
import { rateSubject } from "../../actions/subject";
import { fetchUsers } from "../../actions/authActions";
import { rateUser } from "../../actions/authActions";
import { rateComment } from "../../actions/comment";
import { trueVote } from "../../actions/subject";
import { mostlyTrueVote } from "../../actions/subject";
import { mostlyFalseVote } from "../../actions/subject";
import { halfAndHalfVote } from "../../actions/subject";
import { falseVote } from "../../actions/subject";
class Subject extends Component {
// on loading the subjects and comments
// are fetched from the database
componentDidMount() {
this.props.fetchLatestSubjects();
this.props.fetchComments();
this.props.fetchUsers();
console.log(
fetch("https://extreme-ip-lookup.com/json").then((res) => res.json())
);
}
constructor(props) {
super(props);
this.state = {
// set inital state for subjects
// description,summary and comments all invisible
viewDesription: -1,viewSummary: -1,comments: [],topic: "subjects",};
}
componentWillReceiveProps(nextProps) {
// new subject and comments are added to the top
// of the arrays
if (nextProps.newPost) {
this.props.subjects.unshift(nextProps.newPost);
}
if (nextProps.newPost) {
this.props.comments.unshift(nextProps.newPost);
}
}
clickHandler = (id) => {
// when a subject title is clicked pass in its id
const { viewDescription } = this.state;
this.setState({ comments: [] });
var temp = [];
// get the details of the author of the subject and save to state
const subject = this.props.subjects.find((subject) => subject._id === id);
const user = this.props.users.find((user) => user._id === subject.author);
// save comments for subject to temp array
var i;
for (i = 0; i < this.props.comments.length; i++) {
if (this.props.comments[i].subject === id) {
temp.unshift(this.props.comments[i]);
}
}
console.log(temp);
// for each comment add a property with the authors name
temp.forEach((comment) => {
var commentAuthor = this.props.users.find(
(user) => user._id === comment.author
);
comment.authName = commentAuthor.name;
});
// save the subject id to local storage
// this is done incase a new comment is added
// then the subject associated with it can be retrieved
// and added as a property of that comment
localStorage.setItem("passedSubject",id);
localStorage.setItem("passedTopic",subject.topic);
// add all changes to the state
this.setState({
viewDescription: viewDescription === id ? -1 : id,comments: temp,subAuthor: user.name,authRating: user.rating,authNoOfVotes: user.noOfVotes,});
};
// hovering on and off subjects toggles the visibility of the summary
hoverHandler = (id) => {
this.setState({ viewSummary: id });
};
hoverOffHandler = () => {
this.setState({ viewSummary: -1 });
};
rateHandler = (id,rate,item) => {
if (item === "subject") {
// this function rates the subject and the author
const subject = this.props.subjects.find((subject) => subject._id === id);
const author = this.props.users.find(
(user) => user._id === subject.author
);
// call the rateSubject and rateUser functions
this.props.rateSubject(id,subject.noOfVotes,subject.rating);
this.props.rateUser(author._id,author.noOfVotes,author.rating);
console.log(author.name);
alert("Thank you for rating this subject.");
} else if (item === "comment") {
const comment = this.props.comments.find((comment) => comment._id === id);
const author = this.props.users.find(
(user) => user._id === comment.author
);
// call the rateComment and rateUser functions
this.props.rateComment(id,comment.noOfVotes,comment.rating);
this.props.rateUser(author._id,author.rating);
console.log(author.name);
alert("Thank you for rating this comment.");
}
};
voteHandler = (id,currVote,vote) => {
if (vote === "True") {
console.log(id,vote);
this.props.trueVote(id,currVote);
alert("Thanks for voting!");
window.location.reload(false);
} else if (vote === "False") {
console.log(id,vote);
this.props.falseVote(id,currVote);
alert("Thanks for voting!");
window.location.reload(false);
} else if (vote === "mostlyFalse") {
console.log(id,vote);
this.props.mostlyFalseVote(id,currVote);
alert("Thanks for voting!");
window.location.reload(false);
} else if (vote === "mostlyTrue") {
console.log(id,vote);
this.props.mostlyTrueVote(id,currVote);
alert("Thanks for voting!");
window.location.reload(false);
} else if (vote === "halfAndHalf") {
console.log(id,vote);
this.props.halfAndHalfVote(id,currVote);
alert("Thanks for voting!");
window.location.reload(false);
}
};
render() {
const subjectItems = this.props.subjects.map((subject) => {
// if the state equals the id set to visible if not set to invisible
var view = this.state.viewDescription === subject._id ? "" : "none";
var hover = this.state.viewSummary === subject._id ? "" : "none";
var comments = this.state.comments;
var subjectAuthor = this.state.subAuthor;
var authRating = this.state.authRating;
var authNoOfVotes = this.state.authNoOfVotes;
var className = "";
if (subject.category === "Education") {
className = "Education";
} else if (subject.category === "Environment") {
className = "Environment";
} else if (subject.category === "Politics") {
className = "Politics";
} else if (subject.category === "Health") {
className = "Health";
} else if (subject.category === "Other") {
className = "Other";
}
return (
<div key={subject._id}>
<div
className={className}
onMouseEnter={() => this.hoverHandler(subject._id)}
onMouseLeave={() => this.hoverOffHandler()}
>
<p className="title" onClick={() => this.clickHandler(subject._id)}>
{subject.title}
</p>
<p className="vote" style={{ textAlign: "Right" }}>
Rating: {(subject.rating / subject.noOfVotes).toFixed(1)}/5
</p>
<p className="summary" style={{ display: hover }}>
{subject.summary}
</p>
</div>
<div className="truthResult" style={{ display: view }}>
<p className="false">
FALSE -{" "}
{(
(100 /
(subject.true +
subject.false +
subject.mostlyTrue +
subject.mostlyFalse +
subject.halfAndHalf)) *
subject.false
).toFixed(1)}
%
</p>
<p className="mostlyFalse">
MOSTLY FALSE -{" "}
{(
(100 /
(subject.true +
subject.false +
subject.mostlyTrue +
subject.mostlyFalse +
subject.halfAndHalf)) *
subject.mostlyFalse
).toFixed(1)}
%
</p>
<p className="halfAndHalf">
HALF AND HALF -{" "}
{(
(100 /
(subject.true +
subject.false +
subject.mostlyTrue +
subject.mostlyFalse +
subject.halfAndHalf)) *
subject.halfAndHalf
).toFixed(1)}
%
</p>
<p className="mostlyTrue">
MOSTLY TRUE -{" "}
{(
(100 /
(subject.true +
subject.false +
subject.mostlyTrue +
subject.mostlyFalse +
subject.halfAndHalf)) *
subject.mostlyTrue
).toFixed(1)}
%
</p>
<p className="true">
TRUE -{" "}
{(
(100 /
(subject.true +
subject.false +
subject.mostlyTrue +
subject.mostlyFalse +
subject.halfAndHalf)) *
subject.true
).toFixed(1)}
%
</p>
</div>
<div className="subjectBody " style={{ display: view }}>
<div className="leftSubjectBody">
<div className="subjectAuthor">
<p className="author">
Subject created by: {subjectAuthor} -{" "}
{(authRating / authNoOfVotes).toFixed(1)}/5 Star user
{/* <br /> {subject.date} */}
</p>
</div>
<div className="subjectDescription">
<p className="description">{subject.description}</p>
</div>
<div className="subjectLinks">
Supporting Link: <br />
<a href={subject.links} target="blank">
{subject.links}
</a>
</div>
</div>
<div className="rightSubjectBody">
<div className="rate">
<p>
<b>Rate this subject</b>
</p>
<button
onClick={() => this.rateHandler(subject._id,1,"subject")}
>
1
</button>
<button
onClick={() => this.rateHandler(subject._id,2,"subject")}
>
2
</button>
<button
onClick={() => this.rateHandler(subject._id,3,"subject")}
>
3
</button>
<button
onClick={() => this.rateHandler(subject._id,4,"subject")}
>
4
</button>
<button
onClick={() => this.rateHandler(subject._id,5,"subject")}
>
5
</button>
</div>
<div className="voting">
<p>
Do you think this subject question is false,mostly false,half and half,mostly true or true,based on the evidence
provided and your own reseach in the area? Please vote below
and leave comments.
</p>
<div
className="voteButton"
onClick={() =>
this.voteHandler(subject._id,subject.false,"False")
}
>
FALSE
</div>
<div
className="voteButton"
onClick={() =>
this.voteHandler(
subject._id,subject.mostlyFalse,"mostlyFalse"
)
}
>
MOSTLY FALSE
</div>
<div
className="voteButton"
onClick={() =>
this.voteHandler(
subject._id,subject.halfAndHalf,"halfAndHalf"
)
}
>
HALF AND HALF
</div>
<br />
<div
className="voteButton"
onClick={() =>
this.voteHandler(
subject._id,subject.mostlyTrue,"mostlyTrue"
)
}
>
MOSTLY TRUE
</div>
<div
className="voteButton"
onClick={() =>
this.voteHandler(subject._id,subject.true,"True")
}
>
TRUE
</div>
</div>
</div>
<div className="subjectComments">
<p style={{ fontWeight: "bold" }}>Comments:</p>
{comments.map((comment,i) => {
return (
<div key={i} className="singleComment">
<p>
{comment.title} - Comment rating :{" "}
{(comment.rating / comment.noOfVotes).toFixed(1)}/5
<br />
{comment.comment}
<br />
Comment by : {comment.authName} - This user has a rating
of {(comment.rating / comment.noOfVotes).toFixed(1)}/5
STARS
</p>
<div className="rate">
Rate this comment :{" "}
<button
onClick={() =>
this.rateHandler(comment._id,"comment")
}
>
1
</button>
<button
onClick={() =>
this.rateHandler(comment._id,"comment")
}
>
2
</button>
<button
onClick={() =>
this.rateHandler(comment._id,"comment")
}
>
3
</button>
<button
onClick={() =>
this.rateHandler(comment._id,"comment")
}
>
4
</button>
<button
onClick={() =>
this.rateHandler(comment._id,"comment")
}
>
5
</button>
</div>
</div>
);
})}
<br />
<a href="/addcomment">
<div className="buttonAddComment">ADD COMMENT</div>
</a>
</div>
</div>
</div>
);
});
return (
<div id="Subject">
<GoogleSearch />
{subjectItems}
</div>
);
}
}
Subject.propTypes = {
fetchLatestSubjects: PropTypes.func.isRequired,fetchTopicSubjects: PropTypes.func.isRequired,fetchTopicComments: PropTypes.func.isRequired,fetchComments: PropTypes.func.isRequired,fetchUsers: PropTypes.func.isRequired,rateSubject: PropTypes.func.isRequired,rateComment: PropTypes.func.isRequired,rateUser: PropTypes.func.isRequired,trueVote: PropTypes.func.isRequired,falseVote: PropTypes.func.isRequired,subjects: PropTypes.array.isRequired,comments: PropTypes.array.isRequired,users: PropTypes.array.isRequired,newPost: PropTypes.object,};
const mapStateToProps = (state) => ({
subjects: state.subjects.items,newSubject: state.subjects.item,comments: state.comments.items,users: state.auth.users,newComment: state.comments.item,});
// export default Subject;
export default connect(mapStateToProps,{
fetchLatestSubjects,fetchTopicSubjects,fetchTopicComments,fetchComments,fetchUsers,rateSubject,// rate subject
rateUser,rateComment,trueVote,mostlyTrueVote,falseVote,mostlyFalseVote,halfAndHalfVote,})(Subject,Comment);
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)