我正在学习redux,我很难理解它。 我有一个文章列表,每个文章都包含标题和URL。 我想获取当前文章的网址,并将其传递给其他组件以显示预览网址
当我单击按钮以放置Article.js中的其他组件时,我试图传递当前文章的url,但是它不起作用。它仅显示所有文章的所有网址。 如果有人可以帮助我或向我解释我的错,那可能会很好。
在actions.js中
export const articleClick = url => ({
type: SHOW_ARTCILE,
payload: { url }
});
在redux中,article.js
article: null
}
const articleReducer = (state = INITIAL_STATE, action) => {
switch (action.type) {
case 'SHOW_ARTCILE':
return [
...state,
{
url: action.url,
}
]
;
default:
return state;
}
}
export default articleReducer;
在Article.js中
import { articleClick } from '../../redux/actions';
import { connect } from "react-redux";
class Article extends Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<p>{this.props.article.title}</p>
<div>
<p>Posted by : {this.props.article.by}</Posted>
<button onClick={() => this.props.articleClick(this.props.article.url), console.log(this.props.article.url)}>Visit website</button>
</div>
</div>
)
}
}
export default connect(
null,
{ articleClick }
)(Article);
在Preview.js中
import { connect } from "react-redux";
import { articleClick } from '../../redux/actions';
class PreviewArticle extends Component {
render() {
return (
<p>
{this.url}
</p>
);
}
}
export default connect(
null,
{ articleClick }
)(PreviewArticle);
答案 0 :(得分:1)
让我们在此处尝试优化您的react-redux流程,以便我们可以更轻松地进行解释。
首先让我们尝试使您的App组件看起来像这样:
index.js
import React from "react";
import ReactDOM from "react-dom";
import { Provider } from "react-redux";
import { createStore, combineReducers } from "redux";
import articles from "./reducers/articles";
import Articles from "./components/Articles";
import Preview from "./components/Preview";
const store = createStore(
combineReducers({
articles: articles
})
);
function App() {
return (
<Provider store={store}>
<div className="App">
<Articles />
<Preview />
</div>
</Provider>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
主要组件显示“文章”组件和“预览”组件。此外,我们将redux-store提供给Main组件。
让我们看看构成我们的redux商店的所有方面。
reducers.js
const initialState = {
articles: [
{
title: "Corgi",
url: "https://www.akc.org/dog-breeds/cardigan-welsh-corgi/"
},
{
title: "Leopard Dog",
url: "https://www.akc.org/dog-breeds/catahoula-leopard-dog/"
}
],
article: {}
};
const articlesReducer = (state = initialState, action) => {
switch (action.type) {
case "SHOW_URL":
return {
...state,
article: action.payload
};
default:
return state;
}
};
export default articlesReducer;
在化简器中,我们具有一个默认状态,该状态包含一个对象(文章)数组和一个当前文章。我们将使用这两者来填充“文章”和“预览”组件的显示。减速器的唯一更新时间是调度了类型为“ SHOW_URL”的操作,因此,我们将更新当前文章。
在 actions.js 中查看动作创建者:
export const showUrl = article => {
return {
type: "SHOW_URL",
payload: article
};
};
现在是我们的组件,文章,文章和预览。
在文章中,我们需要使用 mapStateToProps 来获取Redux状态下可用的文章列表。然后,我们遍历每篇文章并呈现一个单独的Article
组件。通过,将迭代的文章作为道具。
import React from "react";
import { connect } from "react-redux";
import Article from "./Article";
const Articles = ({ articles }) => {
return (
<div>
{articles.articles.map(article => {
return <Article article={article} />;
})}
</div>
);
};
const mapStateToProps = state => {
return {
articles: state.articles
};
};
export default connect(mapStateToProps)(Articles);
现在,在每个唯一的Article组件中,我们都使用动作创建器,将收到的文章作为更新Redux状态的道具进行传递。
import React from "react";
import { connect } from "react-redux";
import { showUrl } from "../actions/articleActions";
const Article = ({ article, showUrl }) => {
return (
<div>
<button onClick={() => showUrl(article)}>{article.title}</button>
</div>
);
};
const mapDispatchToProps = dispatch => {
return {
showUrl: article => {
dispatch(showUrl(article));
}
};
};
export default connect(
null,
mapDispatchToProps
)(Article);
操作完成后,Reducer会获得更新状态,这会导致我们的Preview
组件重新呈现并反映该更新后的数据。
import React from "react";
import { connect } from "react-redux";
const Preview = ({ articles }) => {
const thisArticle = articles.article;
return (
<div>
<h4>{thisArticle.title}</h4>
<a href={thisArticle.url}>Go To Link</a>
</div>
);
};
const mapStateToProps = state => {
return {
articles: state.articles
};
};
export default connect(mapStateToProps)(Preview);
我在这里为您创建了一个示例代码和框供您参考:https://codesandbox.io/s/simple-redux-with-dogs-s1v6h