我正在学习 React 和 Redux,在学习的同时我决定制作一个带有按钮的网页,单击该按钮会改变状态。在按钮下方,我想在不同的组件中显示当前状态。虽然单击按钮会更改状态,但它不会反射(reflect)在组件中。这是我的代码:
App.js
import React from 'react'
import Name from './Name'
import {changeName} from './Action';
export default function App () {
return (
<div>
<button onClick={changeName}>Click me</button>
<Name />
</div>
)
}
名称.js
import React from 'react'
import {store} from './Store'
function Name(props) {
return (
<div>
My name is: {store.getState()}
</div>
)
}
export default Name
商店.js
import { createStore } from 'redux';
import {reducer} from './Reducer';
export const store = createStore(reducer, 'Tarun');
Action .js
import {store} from './Store';
export const changeName = () => {
if (store.getState() === "Tarun"){
store.dispatch({ type: 'name', payload: 'Subhash' });
}
else{
store.dispatch({ type: 'name', payload: 'Tarun' });
}
}
Reducer.js
export const reducer = function(state, action) {
if (action.type === 'name') {
return action.payload;
}
return state;
};
当我点击按钮时,Name 组件中的文本没有改变。什么问题?
最佳答案
您需要按照 Redux 文档正确设置 reducer 和初始存储。
您缺少一个 Provider
,它将为您的应用程序提供您的 store
。
const store = createStore(reducer, applyMiddleware(thunk));
const rootElement = document.getElementById("root");
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
rootElement
);
现在,您的商店可供您的组件使用。
您的 reducer
也需要一个初始状态,并且您总是应该返回状态的更新副本。也就是说,不要直接更改状态,而是制作一个副本,更改它,然后返回该副本。
const initialState = {
name: ""
};
const reducer = function(state = initialState, action) {
if (action.type === "name") {
return { ...state, name: action.payload };
} else {
return state;
}
};
export default reducer;
您可能已经注意到我在您的商店中添加了一个中间件,那是因为在您的操作中访问当前 reducer 的状态时通常采用这种方式。也就是说,我为此安装了 redux-thunk,所以在你的操作中,你可以有这样的东西:
export const changeName = () => {
return (dispatch, getState) => {
if (getState().name === "Tarun") {
dispatch({ type: "name", payload: "Subhash" });
} else {
dispatch({ type: "name", payload: "Tarun" });
}
};
};
现在,您的商店已提供给您的应用程序,您的 reducer 已经完成并且您的操作已准备就绪,您可以将不同的组件连接到您的 reducer 。
您为此使用了 react-redux
中名为 connect
的高阶组件。例如,在您的 Name
组件中,我们可以通过将您的状态映射到组件的 props 来将要显示的名称连接到您的 reducer:
function Name(props) {
return <div>My name is: {props.name}</div>;
}
const mapStateToProps = state => {
return {
name: state.name
};
};
export default connect(mapStateToProps)(Name);
这里的好处是您还可以将 connect
高阶组件中的第一个参数留空,只传递第二个参数,这将是调度函数。好吧,这就是您要在 App
组件中执行的操作,您会将其连接到 changeName
操作。
function App(props) {
return (
<div>
<button onClick={props.changeName}>Click me</button>
<Name />
</div>
);
}
const mapDispatchToProps = dispatch => {
return {
changeName: () => dispatch(changeName())
};
};
export default connect(
null,
mapDispatchToProps
)(App);
现在,当 App 调度一个 changeName
操作时,您的 reducer 状态将被更新,并且连接到 reducer 状态的其他组件将重新呈现。
总结:尝试将您的商店想象成一 jar 空糖果。你的 jar 一开始是空的,但不同的 Action 可能会改变 jar 里的东西。最重要的是,房子里知道 jar 在哪里的不同人可以去拿一些糖果。转化为您的问题,您的应用程序以一个空名称开头,并且您有一个设置名称的操作。通过连接到您的 reducer 知道在哪里可以找到该名称的组件将知道该名称何时更改并将获得更新后的名称。
最终代码可以在这里找到:
关于javascript - 通过 redux 更改状态后如何更新 React 组件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58249720/