J'essaie d'avoir une page de filtre alimentaire dans laquelle l'utilisateur appuie sur des boutons pour indiquer sa préférence afin que, lors de la confirmation, je puisse avoir la préférence de l'utilisateur stockée comme sur un objet avec des clés "area", "cuisine" and "price". Après avoir essayé diverses combinaisons, l'objet enregistré que j'obtiens ne reflète qu'un changement dans la première mise à jour qui est area. {"area": "South", "cuisine": Array [], "price": -Infinity } au lieu de {"area":"South", "cuisine": "Japanese Cuisine", "price": 3}. Comment gérer cette nature asynchrone de setstate pour que toutes les mises à jour soient correctes? (les fonctions de presse à poignée sont transmises au composant enfants pour la cuisine de la région et le prix)

enter image description here

Filter.js

const [filters, setFilters] = React.useState({});

    React.useEffect(() => {
        setFilters({ area: "", cuisine: "", price: 0 });
    }, []);

    const handleAreaPress = (area) => {
        setFilters((prevState) => ({ ...prevState, area: area }));
    };

    const handleCuisinePress = (cuisine) => {
        setFilters((prevState) => ({ ...prevState, cuisine: cuisine }));
    };

    const handlePricePress = (price) => {
        let max = Math.max(...price);
        setFilters((prevState) => ({ ...prevState, price: max }));
    };

    const handleConfirmPress = () => {
        console.log(filters);  // expected log to be {"area":"South", "cuisine": "Japanese Cuisine", "price": 3}
    };

Area.js

const AreaSelection = ({ handleAreaPress }) => {
    const [selected, setSelected] = React.useState([]);
    const areas = ["North", "South", "East", "West", "Central"];

    const handlePress = (area) => {
        setSelected(area);
    };

    const buttons = () =>
        areas.map((items) => (
            <TouchableOpacity
                key={items}
                onPress={() => {
                    handlePress(items);
                    handleAreaPress(items);
                }}
                style={[
                    styles.button,
                    {
                        backgroundColor: selected.includes(items)
                            ? "silver"
                            : "white",
                    },
                ]}
            >

Cuisine.js

const CuisineSelection = ({ handleCuisinePress }) => {
    const [selected, setSelected] = React.useState([]);
    const cuisine = [
        "Asian",
        "Western",
        "Chinese",
        "Korean",
        "Indian",
        "Japanese",
        "Cafe",
        "Local",
    ];

    const handlePress = (cuisine) => {
        selected.includes(cuisine)
            ? setSelected(selected.filter((s) => s !== cuisine))
            : setSelected([...selected, cuisine]);
    };

    const buttons = () =>
        cuisine.map((items) => (
            <TouchableOpacity
                key={items}
                onPress={() => {
                    handlePress(items);
                    handleCuisinePress(selected);
                }}
                style={[
                    styles.button,
                    {
                        backgroundColor: selected.includes(items)
                            ? "silver"
                            : "white",
                    },
                ]}
            >
0
Rui Feng 18 juin 2020 à 11:32

3 réponses

Meilleure réponse

L'indicatif régional fonctionne correctement. Le problème est dans ce code où vous appelez l'état de réglage de deux fonctions:

    handlePress(items);
    handleCuisinePress(selected);

handlePress définit l'état du composant interne, puis handleCuisinePress lit cet état et le définit sur les filtres. Cependant, comme le paramètre state est asynchrone lorsque handleCuisinePress est appelé, il utilise les anciennes valeurs d'état puisque les résultats handlePress ne sont pas encore appliqués.

La meilleure façon de gérer cela serait de se débarrasser de l'état du composant interne et de le lire directement à partir des filtres:

// Declare array outside of component to not create it on every render
const cuisine = [
        "Asian",
        "Western",
        "Chinese",
        "Korean",
        "Indian",
        "Japanese",
        "Cafe",
        "Local",
    ];

const CuisineSelection = ({ handleCuisinePress, cuisine }) => {
    const buttons = () =>
        cuisine.map((items) => (
            <TouchableOpacity
                key={items}
                onPress={() => {
                    handleCuisinePress(items);
                }}

            >
1
Clarity 18 juin 2020 à 09:09
 const handlePress = (cuisine) => {
    let newSelected = [];

    if (selected.includes(cuisine)) {
      newSelected = selected.filter((s) => s !== cuisine);
    } else {
      newSelected = selected.concat(cuisine);
    }

    setSelected(cuisine);
    handleCuisinePress(newSelected);
};

L'état selected que vous passez à handleCuisinePress n'est pas à jour, vous ne devriez pas vous y fier, passez simplement le nouvel état que vous avez calculé dans handlePress à handleCuisinePress

1
Yu Mao 18 juin 2020 à 09:12

Vous pouvez définir une plage de valeurs attendues et revenir conditionnellement à une valeur par défaut.

    const handlePricePress = (price) => {
        const max = price >= 0 ? Math.max(...price) : 0;
        setFilters((prevState) => ({ ...prevState, price: max }));
    };
0
sebastian-ruehmann 18 juin 2020 à 08:43