我正在尝试使用React-Redux建立一个简单的网站,以练习使用React和Redux并将它们连接起来。整个HTML只是一个id为“ container”的div,用于在代码末尾从ReactDOM.render接收最终组件。
// Redux
const defaultState = {
input: ""
}
const updateView = (event) => {
return {
type: "UPDATE",
input: event.target.value
}
}
const reducer = (state = defaultState, action) => {
switch(action.type) {
case "UPDATE":
return {
input: action.input
}
default:
return state
}
}
const store = Redux.createStore(reducer);
// React Redux
const connect = ReactRedux.connect;
const Provider = ReactRedux.Provider;
// React
class Presentational extends React.Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
}
handleChange(event) {
dispatch(this.props.submitUpdate(event));
}
render() {
return (
<div>
<textarea cols="40" rows="10" value={this.props.input} onChange={this.handleChange}/>
<div id="preview"></div>
</div>
)
}
}
const mapStateToProps = (state) => {
return {
input: state.input
}
}
const mapDispatchToProps = (dispatch) => {
return {
submitUpdate: function(event) {
dispatch(updateView(event));
}
}
}
const Container = connect(mapStateToProps, mapDispatchToProps)(Presentational);
class App extends React.Component {
constructor(props) {
super(props)
}
render() {
<Provider store={store}>
<Container/>
</Provider>
}
}
ReactDOM.render(<App />, document.getElementById("container"));
我最终希望它成为Markdown预览器,但是现在我希望它呈现一个我可以输入的文本区域,并且在后台它应该更改state的input属性,以便以后可以访问它。相反,它什么也不渲染并抛出:
[object Error] {
framesToPop: 1,
name: "Invariant Violation"
}
答案 0 :(得分:1)
问题出在您的App
组件中。您错过了那里的return
,因此render方法默认情况下返回undefined
,这就是导致您看到错误的原因。另一个解决方法是,一旦修复了dispatch
组件中缺失的收益,就将删除App
,这将给您运行时间错误。
更正后的App
组件是:
class App extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<Provider store={store}>
<Container />
</Provider>
);
}
}
dispatch(this.props.submitUpdate(event));
应该位于this.props.submitUpdate(event);
组件Presentational
方法内的handleChange
。
完整的工作代码:
index.js
// Redux
const defaultState = {
input: ""
};
const updateView = event => {
return {
type: "UPDATE",
input: event.target.value
};
};
const reducer = (state = defaultState, action) => {
switch (action.type) {
case "UPDATE":
return {
input: action.input
};
default:
return state;
}
};
const store = Redux.createStore(reducer);
// React Redux
const connect = ReactRedux.connect;
const Provider = ReactRedux.Provider;
// React
class Presentational extends React.Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
}
handleChange(event) {
this.props.submitUpdate(event);
}
render() {
return (
<div>
<textarea
cols="40"
rows="10"
value={this.props.input}
onChange={this.handleChange}
/>
<div id="preview" />
</div>
);
}
}
const mapStateToProps = state => {
return {
input: state.input
};
};
const mapDispatchToProps = dispatch => {
return {
submitUpdate: function(event) {
dispatch(updateView(event));
}
};
};
const Container = connect(
mapStateToProps,
mapDispatchToProps
)(Presentational);
class App extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<Provider store={store}>
<Container />
</Provider>
);
}
}
ReactDOM.render(<App />, document.getElementById("container"));
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<script
crossorigin
src="https://unpkg.com/react@16/umd/react.development.js"
></script>
<script
crossorigin
src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"
></script>
<script src="https://unpkg.com/react-redux@6.0.0/dist/react-redux.js"></script>
<script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>
<script src="https://unpkg.com/redux@4.0.1/dist/redux.js"></script>
<title>Document</title>
</head>
<body>
<div id="container"></div>
<script type="text/babel" src="index.js"></script>
</body>
</html>