gpt4 book ai didi

javascript - 如何不用空白状态覆盖调度

转载 作者:行者123 更新时间:2023-11-30 20:54:59 24 4
gpt4 key购买 nike

背景:
我正在实践 React/Redux 的想法。我想跟随数据流。
axios 调度 action -> reducer setState 到 props -> Component render()

问题可能不止1分。因为我是 Frontend 世界的新手。请随时重新设计我的应用程序(如果需要)

问题:
company 没有渲染出来,因为 this.props.companies 是空白的。但是 axios 确实从后端获取数组。

action/index.js

//First experiment action returns promise instance
export function fetchCompanies(token) {
const jwtReady = 'JWT '.concat(token);
const headers = {
'Content-Type': 'application/json',
'Authorization': jwtReady
};
const instance = axios({
method: 'GET',
url: `${ROOT_URL}/api/companies/`,
headers: headers
});
return {
type: FETCH_COMPANIES,
payload: instance
}
}

export function getCompanies(token){
const jwtReady = 'JWT '.concat(token);
const headers = {
'Content-Type': 'application/json',
'Authorization': jwtReady
};
const instance = axios({
method: 'GET',
url: `${ROOT_URL}/api/companies/`,
headers: headers
});
return instance
.then(data=> store.dispatch('GET_COMPANIES_SUCCESS', data));
}

company_reducers.js

import {FETCH_COMPANIES, GET_COMPANIES_ERROR, GET_COMPANIES_SUCCESS} from "../actions/const";


export default function (state = {}, action) {
switch (action.type) {
case GET_COMPANIES_SUCCESS:
return {
...state,
companies: action.payload
};
case GET_COMPANIES_ERROR:
return {
...state,
err_msg: action.payload.text
};
default:
return state;
}
}

reducers/index.js

import {combineReducers} from 'redux';
import {reducer as formReducer} from 'redux-form';
import LoginReducer from './login_reducers';
import CompanyReducer from './company_reducers';

const rootReducer = combineReducers({
login: LoginReducer,
companies: CompanyReducer,
form: formReducer
});

export default rootReducer;

component/select_teams.js

import _ from 'lodash';
import React, {Component} from 'react';
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import {fetchCompanies, getCompanies} from "../actions";
import {Link} from 'react-router-dom';

class SelectTeam extends Component {
constructor(props) {
super(props);
const token = localStorage.getItem('token');
this.state = {
token,
companies: null,
err_msg: null
}
}

componentWillMount() {
const tmp = this.props.getCompanies(this.state.token);
tmp.then(res => {
console.log(res)
})
.catch(err => {
console.log(err);
})
};

renderErrors() {
return (
<div>{this.state.err_msg}</div>
);
}

renderCompanies() {
return _.map(this.props.companies, company => {
return (
<li className="list-group-item" key={company.id}>
<Link to={`/${company.id}`}>
{company.name}
</Link>
</li>
)
});
}

render() {
if (this.props.companies === null) {
return (
<div>Loading...</div>
);
}
console.log(this.props);

return (
<div>
<h3>&#10084; Select Team &#10084;</h3>
{this.renderErrors()}
{this.renderCompanies()}
</div>
);
}
}

function mapStateToProps(state){
return {companies: state.companies}
}

function mapDispatchToProps(dispatch) {
return bindActionCreators({
fetchCompanies: fetchCompanies,
getCompanies: getCompanies
}, dispatch);
}

export default connect(mapStateToProps, mapDispatchToProps)(SelectTeam);

App.js

import React, {Component} from 'react';
import './App.css';
import SelectTeam from "./components/select_teams";
import reducers from './reducers/index';
import {Provider} from 'react-redux';
import promise from "redux-promise";
import {applyMiddleware, createStore} from 'redux';
import {BrowserRouter, Route, Switch, Redirect} from 'react-router-dom';
import LoginPage from './components/loginPage';

const createStoreWithMiddleware = applyMiddleware(promise)(createStore);

const PrivateRoute = ({component: Component, isAuthorized, ...otherProps}) => (
<Route
{...otherProps}
render={props => (
isAuthorized() ? (<Component {...props} />) :
(
<Redirect to={
{
pathname: '/login',
state: {from: props.location},
}
}
/>
)
)}
/>
);

function PageNotFound() {
return (
<div>404 Page Not Found</div>
);
}

// TODO: I will add RESTful validation with backend later
function hasToken() {
const token = localStorage.getItem('token');
const isAuthenticated = !((token === undefined) | (token === null));
return isAuthenticated;
}

export const store = createStoreWithMiddleware(reducers);

class App extends Component {
//I will add security logic with last known location later.
//Get the features done first
render() {
return (
<Provider store={store}>
<BrowserRouter>
<div>
<Switch>
<PrivateRoute exact path="/select-teams" isAuthorized={hasToken} component={SelectTeam}/>
<Route path="/login" component={LoginPage}/>
<Route component={PageNotFound}/>
</Switch>
</div>
</BrowserRouter>
</Provider>
);
}
}

export default App;

最佳答案

您应该使用从服务器获取的数据发送一个操作。操作是返回一个对象的纯函数(该对象至少有一个 TYPE 字段)。如果你有任何异步操作,你可以使用 Redux-Thunk ,这是一个返回函数的 Action 创建器,并在其中调用 api fetch。

这是actions片段:

// imports..
export const fetchCompaniesSuccess = (data) => {
retyrn {
type: FETCH_COMPANIES_SUCCESS,
data
}
}


export const fetchCompanies = (token) => dispatch => {
// ...
axios(...).then(dispatch(data => fetchCompaniesSuccess(data)))
}

在你的 company_reducers.js 中,

// Company Reducer Function, State here represents only the companies part of the store
case FETCH_COMPANIES_SUCCESS: // should match the the type returned by the action
return [
...state,
...action.data
]
// other cases & default

确保redux-thunk 添加为您的createStore 中的中间件,阅读Redux-Thunk文档以获取说明。

然后在你的组件中:

componentDidMount(){
this.props.fetchCompanies(this.state.token);
}

将公司数据添加到 redux 存储后,您的组件将重新呈现,并且 companies 数组将在 props 中可用您不需要在组件状态中有一个重复的 companies 数组。

您可能想观看 Dan Abramov introduction to redux , 这是一门免费类(class)。

关于javascript - 如何不用空白状态覆盖调度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47765479/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com