首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用redux-thunk分派操作让connected-react-router重定向?

如何使用redux-thunk分派操作让connected-react-router重定向?
EN

Stack Overflow用户
提问于 2018-06-19 01:16:23
回答 2查看 12.2K关注 0票数 3

我正在做一个新的项目。我正在使用create-react-app和redux和thunk。api服务器是一个单独的项目,使用node/express和mongo/mongoose作为数据库。在执行创建或删除项目操作后,我正在尝试重定向到项目列表视图。如果重定向在组件本身中,则重定向在操作完成之前发生,列表的重新获取发生在创建或删除发生之前。因此,我尝试使用thunk在操作的.then()部分中分派一个重定向操作。重定向成功更改了浏览器中的url,但不会触发重新呈现。如何从create操作或delete操作获得重定向,以触发stockitems list组件的重新呈现?

完整代码在:https://github.com/jhlindell/BarCode-app/tree/stockitem服务器位于:https://github.com/jhlindell/BarCode-server/tree/jon

我的index.js:

代码语言:javascript
复制
import 'bootstrap/dist/css/bootstrap.css';
import './index.css';
import App from './App';
import { Provider } from 'react-redux';
import React from 'react';
import ReactDOM from 'react-dom';
import registerServiceWorker from './registerServiceWorker';
import { ConnectedRouter } from 'connected-react-router'

import { createStore, applyMiddleware, compose } from 'redux';
import { composeWithDevTools } from 'redux-devtools-extension';
import { createBrowserHistory } from 'history';
// import { browserHistory } from 'react-router'
import reducers from './reducers';
import thunk from 'redux-thunk';
import { connectRouter, routerMiddleware } from 'connected-react-router'
import { logger } from 'redux-logger';

const history = createBrowserHistory();
const reactRouterMiddleware = routerMiddleware(history); 

const middleWares = [
  thunk,
  logger,
  reactRouterMiddleware
]

const store = createStore(
  connectRouter(history)(reducers), 
  composeWithDevTools(applyMiddleware(...middleWares)));

ReactDOM.render(
  <Provider store = {store}>
    <ConnectedRouter history={history}>
      <App history={history}/>
    </ConnectedRouter>
  </Provider>
, document.getElementById('root'));
registerServiceWorker();

我的app.js文件:

代码语言:javascript
复制
import './App.css';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import Footer from './components/Nav/Footer';
import NavBar from './components/Nav/NavBar';
import React, { Component } from 'react';
import StockItemCreate from './components/StockItems/StockItemCreate';
import StockItemDetail from './components/StockItems/StockItemDetail';
import StockItemList from './components/StockItems/StockItemList';
import HomePage from './components/HomePage';


class App extends Component {
  com

  render() {
    const flexCol = {
      display: 'flex',
      flexDirection: 'column',
    };

    const flex0 = {
      flex: 0
    };

    const flex1 = {
      display: 'flex',
      flex: '1 1 100%',
    };
    return (
      <Router>
        <div className="App" style={flexCol}>
          <div style={flex0}>
            <NavBar />
          </div>
          <div style={flex1} id="mainBlock">
            <Switch>
              <Route exact path='/' component={HomePage} />
              <Route exact path='/stockitems/create' component={StockItemCreate} />
              <Route exact path='/stockitems' component={StockItemList} />
              <Route path='/stockitems/:id' component={StockItemDetail} />
            </Switch>
          </div>
          <div style={flex0}>
            <Footer />
          </div>
        </div>
      </Router>
    );
  }
}

export default App;

list组件:

代码语言:javascript
复制
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import React, {Component} from 'react';
import { getStockItemList, clearStockItemList } from '../../actions';

const listStyle = {
    display: 'flex',
    margin: 'auto'
}

class StockItemList extends Component {
  componentDidMount(){
    this.props.getStockItemList();
  }

  componentWillUnmount(){
    this.props.clearStockItemList();
  }

  render(){
    return (
      <div style={listStyle}>
        {this.props.stockItemList ? <ul className="list-group">
          {this.props.stockItemList.map((item) => {
            return <li 
            className="list-group-item" 
            key={item.name}
            onClick={()=> this.props.history.push(`/stockitems/${item._id}`)}
            >{item.name}</li>
          })}
        </ul> : <span>loading...</span>}
      </div>
    );
  }
}

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

function mapDispatchToProps(dispatch){
  return bindActionCreators({ getStockItemList, clearStockItemList }, dispatch)
}

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

create组件:

代码语言:javascript
复制
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import React, {Component} from 'react';
import { createStockItem } from '../../actions'

const cardStyle = {
  display: 'flex',
  margin: 'auto',
};

const formStyle = {
  display: 'flex',
  flexDirection: 'column',
  width: '80%',
  margin: 'auto'
};

class StockItemCreate extends Component{
  constructor(props){
    super(props);
    this.state = {
      name: '',
      description: ''
    }
  }
  handleFormSubmit = (event) => {
    event.preventDefault();
    this.props.createStockItem(this.state);
    this.clearForm();
    //this.props.history.push('/stockitems');
  }

  handleInputChange = (event) => {
    const target = event.target;
    const value = target.value;
    const name = target.name;
    this.setState({[name]: value});
  }

  clearForm = () => {
    this.setState({ name: '', description: ''});
  }

  render(){
    return(

        <form className="card" onSubmit={this.handleFormSubmit} style={cardStyle}>
            <div className="card-header">
              <h3>Add new ingredient</h3>
            </div>
            <div className="card-block mt-2">
              <div style={formStyle}> 
                <label>Name</label>
                <input name="name" type="text"
                  onChange={(e) => {this.handleInputChange(e)}}
                  placeholder="Name"
                  value={this.state.name}/>             
              </div>
              <div className="mt-2" style={formStyle}> 
                <label>Description</label>
                <input name="description" type="text"
                  onChange={(e) => {this.handleInputChange(e)}}
                  placeholder="Description"
                  value={this.state.description}/>             
              </div>
            </div>
            <div className="btn-group mb-2 mt-2" style={{padding: '0', margin: 'auto'}}>
              <button className="btn btn-primary" type="submit">
                Submit
              </button>
              <button className="btn btn-secondary" type="button" onClick={()=>this.clearForm()}>
                Cancel
              </button>
            </div>
        </form>

    )
  }
}

function mapDispatchToProps(dispatch){
  return bindActionCreators({ createStockItem }, dispatch);
}

export default connect(null, mapDispatchToProps)(StockItemCreate);

最后,调用重定向的操作文件:

代码语言:javascript
复制
import axios from 'axios';
import { push, replace } from 'connected-react-router'


const URL = 'http://localhost:8000';

export function getStockItemList(){
  return function(dispatch){
    axios.get(`${URL}/api/stock_items/`)
      .then((response) => {
        dispatch({ type: 'STOCK_ITEM_LIST', payload: response.data });
      })
      .catch((error) => {
        console.log('error getting stock items');
      });
  }
}

export function clearStockItemList(){
  return { type: 'CLEAR_STOCK_ITEM_LIST' };
}

export function getStockItemById(id){
  return function(dispatch){
    axios.get(`${URL}/api/stock_items/${id}`)
      .then((response) => {
        dispatch({ type: 'SINGLE_STOCK_ITEM', payload: response.data });
      })
      .catch((error) => {
        console.log('error getting stock item by id');
        dispatch(push('/stockitems'));
      });
  }
}

export function clearSingleStockItem(){
  return { type: 'CLEAR_SINGLE_STOCK_ITEM' };
}

export function createStockItem(item){
  return function(dispatch){
    axios.post(`${URL}/api/stock_items/`, item)
      .then((response)=> {
        console.log("response", response);
        dispatch(push('/stockitems'));
      })
      .catch((error) => {
        //create error container to post error to
        console.log('error creating stock item', error);
      });
  }
}

export function deleteStockItem(id){
  return function(dispatch){
    axios.delete(`${URL}/api/stock_items/${id}`)
      .then((response)=> {
        console.log("delete response: ", response);
        dispatch(push('/stockitems'));
      })
      .catch((error) => {
        //create error container to post error to
        console.log('error deleting stock item', error);
      });
  }
}
EN

回答 2

Stack Overflow用户

发布于 2018-08-14 04:06:02

考虑使用connected-react-routerpush作为“操作创建者”,而不是this.props.history.push

票数 3
EN

Stack Overflow用户

发布于 2020-08-15 01:13:02

根据this SO answer

从这一点更改:

代码语言:javascript
复制
    <Switch>
      <Route path="/">
        <Welcome />
      </Route>
      <Redirect to="/" />
    </Switch>

要这样做:

代码语言:javascript
复制
    <Switch>
      <>
        <Route path="/">
          <Welcome />
        </Route>
        <Redirect to="/" />
      </>
    </Switch>

..。对我很管用。

我试图为任何未明确指定的路径实现一个基本的回退重定向,这样像http://localhost:3000/askfjasdf这样的随机路径就会重定向到http://localhost:3000。出于某种原因,将该片段添加为<Switch>的顶级子级确实做到了这一点。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50914528

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档