简体   繁体   English

Mobx 状态不更新

[英]Mobx state does not update

I have 2 mobx stores, product one and cart one, also I have a modal window React component.我有 2 个 mobx 商店,一个是产品,一个是购物车,还有一个模态窗口 React 组件。 What I need to do is to put properties into the modal window with product store method and then push all the properties in a form of an Object into an array in cart store.我需要做的是使用产品商店方法将属性放入模态窗口,然后将所有属性以对象的形式推送到购物车商店中的数组中。 The problem is that I check if an object already exists in the array, but even if you pick different properties, in the end, the state stays the same and the array does not let objects enter.问题是我检查数组中是否已经存在一个对象,但即使你选择了不同的属性,最终状态还是保持不变,数组不让对象进入。 States like size and price do not change at all.大小和价格等状态根本不会改变。

Here are the code pieces:以下是代码片段:

Product store:产品商店:

import axios from "axios";
import {makeAutoObservable} from "mobx";
class PizzaStore {
    weight:number=200;
    size:number=20;
    pizzas:Object[]=[];
    modalProps:any={};
    constructor(){
        makeAutoObservable(this);
    }
    setModalProps=(p:Object)=>{this.modalProps=p};
    setPizzas=(pizzaArr:any)=>{
        this.pizzas=pizzaArr}
    fetchPizzas=()=>{
        axios.get("http://localhost:3000/db.json").then((resp)=>{
    this.setPizzas(resp.data.pizzas);})}
    setWeight=(option:string)=>{
        switch (option){
            case "small":return this.weight;
            case "medium":return this.weight*1.5;
            default:return this.weight*2;
        }
    }
    setSize=(opt:string)=>{
        switch (opt){
            case "small":return this.size
            
            case "medium":return this.size*1.5;
           
            default:return this.size*2;
        }
    }
    setPrice=(opt:string, price:number)=>{
        switch (opt){
            case "small":return price;
            case "medium":return price*1.5;
            default:return price*2;
        }
    }}
const pizzaStore=new PizzaStore();

export default pizzaStore;
        

Cart Store:购物车商店:

import { makeAutoObservable } from "mobx";
interface p{
    p:object,
}
class CartStore{
    cartItems:any=[]
    cartPrice:number=0;
    constructor(){
        makeAutoObservable(this);
    }
    handleSubmitForm=(e:any, p:{})=>{
        e.preventDefault();
        this.handleSubmitProps(p);
    }
    handleSubmitProps=(p:any)=>{
        if(this.cartItems.some((item:any)=>{return item.modalName===p.modalName&&item.modalSize===p.modalSize})){
            console.log(p.modalName, p.modalSize, p.modalPrice)
        }
           
            else{
                console.log("pushed")
                this.cartItems.push(p);
                console.log(p.modalPrice)
            }
            
        }
        
        
   }
    

const cartStore=new CartStore();
export default cartStore;

And the modal window component:和模态窗口组件:

import React from 'react'
import pizzaStore from './stores/PizzaStore'
import {observer} from "mobx-react-lite"
import cartStore from './stores/CartStore';
import { action } from 'mobx';

function ModalWindowComponent({activeModal, setActiveModal}:any){
    
    const [selectedOption, setSelectedOption]=React.useState("small")
    const handleSetOption=(e:any)=>{
            setSelectedOption(e.target.value)
        }
        let modalImageUrl=pizzaStore.modalProps.imageUrl
        let modalName=pizzaStore.modalProps.name
        let modalDesc=pizzaStore.modalProps.description
        let modalSize=pizzaStore.setSize(selectedOption)
        let modalPrice=pizzaStore.setPrice(selectedOption, pizzaStore.modalProps.price)

    return (
        <div className={activeModal?"modal active":"modal"}  onClick={()=>{setActiveModal(false); setSelectedOption("small")}}>
            <div className="modal-content" onClick={(e)=>{e.stopPropagation()}}>
                <div className="modal-content-header">
                    <button onClick={()=>setActiveModal(false)}>Close</button>
                </div>
                <img src={modalImageUrl} className="modal-content-img"/>
                <p className="modal-content-pizza-name">{modalName}</p>
                <p className="modal-content-pizza-desc">{modalDesc}</p>
                <p className="modal-content-pizza-size">{pizzaStore.setSize(selectedOption)}см</p>
                <p className="modal-content-pizza-weight">{pizzaStore.setWeight(selectedOption)}грамм</p>
                <p className="modal-content-pizza-price">{modalPrice}Руб.</p>
                <form className="modal-content-sizes-form" onSubmit={action((e)=>cartStore.handleSubmitForm(e, {modalName, modalDesc, modalSize, modalPrice, modalImageUrl}))}>
                    <label>
                    
                    <input  name="radio-size"value="small" type="radio" onChange={handleSetOption} checked={!activeModal||selectedOption==="small"} className="modal-content-sizes-form-option"/>Маленькая</label>
                    <label>
                    <input  name="radio-size"value="medium" type="radio"  onChange={handleSetOption}checked={selectedOption==="medium"}className="modal-content-sizes-form-option"/>Средняя</label>
                    <label>
                    <input name="radio-size"value="big" type="radio"  onChange={handleSetOption}checked={selectedOption==="big"} className="modal-content-sizes-form-option"/>Большая</label>
                    <button onClick={()=>{setSelectedOption("small");setActiveModal(false);console.log(cartStore.cartItems)}}>Добавить</button>
                </form>
            </div>
        </div>
    )
}

export default observer(ModalWindowComponent)

I've spent many hours trying to understand what's wrong but I couldn't我花了很多时间试图了解出了什么问题,但我做不到

Your description and code is quite hard to follow.您的描述和代码很难理解。 I would suggest making these changes:我建议进行这些更改:

  1. Wrap with runInAction in asynchronous methods like this:runInAction在这样的异步方法中:
    axios.get("http://localhost:3000/db.json")
      .then((resp)=> {
           runInAction(() => {
               this.setPizzas(resp.data.pizzas)
           })
       }
  1. setWeight, setSize and setPrice methods probably should be getters (mobx computed, not action). setWeight、setSize 和 setPrice 方法可能应该是 getter(mobx 计算,而不是 action)。 Add get before the method and you remove () parentheses.在方法之前添加get并删除()括号。 Example:例子:
get setWeight() {
   return ...
}

and then in places where you use it:然后在你使用它的地方:

pizzaStore.setWeight

Are there any errors on the console?控制台上是否有任何错误?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM