Как сделать рендеринг после вызова метода PUT Api? - PullRequest
0 голосов
/ 18 октября 2019

Обновление магазина идет просто отлично, но изменение появляется только после того, как я обновлю страницу. Это мой редуктор:

export default function (state = initialState, action) {
    switch (action.type) {
        case GET_SHIPMENTS:
            return {
                ...state,
                shipments: action.payload
            };
        case GET_SHIPMENTS_BY_BIKER:
            return {
                ...state,
                shipments: action.payload
            };
        case GET_SHIPMENT:
            return {
                ...state,
                shipment: action.payload
            };
        case UPDATE_SHIPMENT:
            return {
                ...state,
                shipment: action.payload
            };
        default:
            return state;
    }
}

это мое действие:

export const updateShipment = (id, shipmentData) => dispatch => {
    const requestOption = {
        method: 'PUT',
        headers: {
            'Content-Type': 'application/json',
        },
        body: JSON.stringify(shipmentData)
    };

    fetch('http://localhost:3002/api/shipments/' + id, requestOption)
        .then(res => res.json())
        .then(shipment =>
            dispatch({
                type: UPDATE_SHIPMENT,
                payload: shipment
            })
        )
        .catch(err => {
            console.log(err);
        });
};

вот компонент реакции, где сначала получают все необходимые объекты, а после обновления я ожидаю получить всеобъекты нуждались в только что сделанной модификации

class BikerToDo extends Component {
    state = {
        biker_id: 1,
        shipment_id: this.props.shipment.id,
        origin: this.props.shipment.origin,
        destination: this.props.shipment.destination,
        order_status: '',
        pickUp_time: this.props.shipment.pickUp_time,
        delivery_time: this.props.shipment.delivery_time,
        id_button_show: 0
    };

    UNSAFE_componentWillMount() {
        this.props.getShipmentsByBiker(this.state.biker_id);
    }

    componentDidMount() {
        this.props.getBikers();
    }

    componentWillReceiveProps(nextProps) {
        if (nextProps.shipment) {
            this.setState({
                shipment_id: nextProps.shipment.id,
                origin: nextProps.shipment.origin,
                destination: nextProps.shipment.destination,
                pickUp_time: nextProps.shipment.pickUp_time,
                delivery_time: nextProps.shipment.delivery_time,
            });
        }
    };

    handleChange = (e) => {
        const {name, value} = e.target;
        this.setState({
            [name]: value,
            id_button_show: 0
        }, () => this.props.getShipmentsByBiker(this.state.biker_id));
    };

    handleStatusChanger = (e, id) => {
        const {name, value} = e.target;
        this.setState({
            [name]: value,
            id_button_show: id
        });
    };

    handleShipment = id => {
        this.props.getShipment(id);
    };

    handleUpdate = () => {
        const id = this.state.shipment_id;
        const shipment = {
            origin: this.state.origin,
            destination: this.state.destination,
            assignee: this.state.biker_id,
            order_status: this.state.order_status,
            pickUp_time: this.state.pickUp_time,
            delivery_time: this.state.delivery_time,
        };

        this.props.updateShipment(id, shipment);

        this.setState({
            id_button_show: 0
        });

    };

    render() {
        const shipmentsByBiker = this.props.shipments.map(shipment => (
            <tbody>
            <tr onClick={() => this.handleShipment(shipment.id)}>
                <td>{shipment.id}</td>
                <td>{shipment.origin}</td>
                <td>{shipment.destination}</td>
                <td><Form.Control as={"select"} name={"order_status"} onChange={e => this.handleStatusChanger(e, shipment.id)}>
                    <option value={"ASSIGNED"} key={"ASSIGNED"}
                            selected={shipment.order_status === "ASSIGNED"}>Choose Action
                    </option>
                    <option value={"PICKED_UP"} key={"PICKED_UP"}
                            selected={shipment.order_status === "PICKED_UP"}>PICKED UP
                    </option>
                    <option value={"DELIVERED"} key={"DELIVERED"}
                            selected={shipment.order_status === "DELIVERED"}>DELIVERED
                    </option>
                </Form.Control></td>
                <td style={{ width: "20%" }}>{shipment.pickUp_time}</td>
                <td style={{ width: "20%" }}>{shipment.delivery_time}</td>
                <td>{shipment.id === this.state.id_button_show &&
                <Button type={"submit"} value={"Edit"} onClick={this.handleUpdate}>Edit</Button>}</td>
            </tr>
            </tbody>
        ));
        return (
            <div>
                <Nav.Link as={Link} to={'/'}>Manager's Dashboard</Nav.Link>
                <h1>To Do</h1>
                <Form.Control as={"select"} name={"biker_id"}
                              onChange={(e) => this.handleChange(e)}>
                    {this.props.bikers.map(biker => (
                        <option value={biker.id} key={biker.id}
                                selected={this.state.id == biker.id}>{biker.name}</option>
                    ))
                    }
                </Form.Control>
                <br/><br/>
                <Table responsive striped bordered hover variant="dark">
                    <thead>
                    <tr>
                        <th>ID</th>
                        <th>Origin</th>
                        <th>Destination</th>
                        <th>Order Status</th>
                        <th>Pick Up Time</th>
                        <th>Delivery Time</th>
                        <th></th>
                    </tr>
                    </thead>
                    {shipmentsByBiker}
                </Table>
            </div>
        );
    }
}

BikerToDo.propTypes = {
    getShipmentsByBiker: PropTypes.func.isRequired,
    getBikers: PropTypes.func.isRequired,
    getShipment: PropTypes.func.isRequired,
    shipments: PropTypes.array.isRequired,
    bikers: PropTypes.array.isRequired,
    shipment: PropTypes.object.isRequired,
    updateShipment: PropTypes.func.isRequired,
};

const mapStateToProps = state => ({
    shipments: state.shipments.shipments,
    bikers: state.bikers.bikers,
    shipment: state.shipments.shipment
});

export default connect(mapStateToProps, {getShipmentsByBiker, getBikers, getShipment, updateShipment})(BikerToDo);

Я пытался вызвать метод GET Api сразу после обновления, но ничего не происходит.

Ответы [ 2 ]

1 голос
/ 18 октября 2019

Я думаю, что проблема связана с функцией отправки curry:

export const updateShipment = (id, shipmentData) => dispatch => {

Обычно функции с карри возвращают некоторое значение для передачи. Асинхронизация (выборка) внутри функции с карри выглядит так, как будто она может вызвать какое-то состояние гонки. Могу поспорить, что это мешает отправке.

Reddit api пример redux docs:

function fetchPosts(subreddit) {
  return dispatch => {
    dispatch(requestPosts(subreddit))
    return fetch(`https://www.reddit.com/r/${subreddit}.json`)
      .then(response => response.json())
      .then(json => dispatch(receivePosts(subreddit, json)))
  }
}

https://redux.js.org/advanced/example-reddit-api

0 голосов
/ 18 октября 2019
  • Вы неправильно настраиваете свой редуктор. Вы должны перебирать массив отгрузок при получении / исправлении синглов
  • Наличие вложенного состояния в редукторах - это антишаблон, даже если состояние перебирается правильно.
  • Имейте в виду, что получение,Обновление и создание отдельной отправки - это обычно одно и то же, когда дело доходит до состояния редукции. Вы можете просто повторно использовать GET_SHIPMENT, когда: исправление, публикация или получение одной отправки
  • Если вам нужно отслеживать поставки байкеров отдельно от обычнойпри отправке в состоянии используется отдельный редуктор

, попробуйте что-то вроде этого:

export default function (state = initialState, action) {
    switch (action.type) {
        case GET_SHIPMENTS:
            return action.payload;
        case GET_SHIPMENTS_BY_BIKER: //if you need to track biker shipments separate from regular shipments in state use a separate reducer
            return action.payload; 
        case GET_SHIPMENT:
            let shipmentFound = false
            const newState = state.map(shipment=>{
                if(shipment.id === action.payload.id){
                    shipmentFound = true
                    return action.payload
                }
                return shipment
            })
            return shipmentFound ? newState : [...newState, action.payload]

        case UPDATE_SHIPMENT: 
                let shipmentFound = false
                const newState = state.map(shipment=>{
                    if(shipment.id === action.payload.id){
                        shipmentFound = true
                        return action.payload
                    }
                    return shipment
                })
                return shipmentFound ? newState : [...newState, action.payload]
            default:
                return state;
        }
    }

, затем в вашем mapStateToProps

const mapStateToProps = state => ({
    shipments: state.shipments,
    bikers: state.bikers.bikers
});

доступ к одной отправке:

const someShipment = this.props.shipments.find(shipment=> shipment.id === 'someID')

(вам, вероятно, также необходимо обновить байкерский редуктор)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...