从子组件更新父组件的状态(选项卡导航器)



我是React和React Native的新手,我正在尝试构建一个烹饪食谱应用程序。我正在尝试从dishcomponents .js更新我在DishTabNavigator.js中的菜肴状态,以便我可以将数据从DishTabNavigator.js发送到firebase,但我不知道如何更新状态。我试着把国家抬起来,但我做不到。这事我已经纠结一天了。如有任何帮助,不胜感激

DishTabNavigator.js

const Tab = createMaterialTopTabNavigator();
export default function MyTabs({ navigation }) {
const [dish, setDish] = useState([{ ingredients: [] }]);
React.useLayoutEffect(() => {
navigation.setOptions({
headerRight: () => (
<TouchableOpacity style={styles.iconright}>
<Text>Send dish to Firebase</Text>
<FontAwesome name="save" size={24} color="black" />
</TouchableOpacity>
),
});
});
return (
<Tab.Navigator>
<Tab.Screen
name="Ingredient"
component={DishIngredients}
ingredients={dish}
/>
</Tab.Navigator>
);
}

DishIngredients.js

class DishIngredients extends Component {
constructor(props) {
super(props);
this.state = {
ingredients: [],
textInput: [],
};
//Add TextInput
addTextInput = (index) => {
let textInput = this.state.textInput;
textInput.push(
<TextInput
style={styles.textInput}
onChangeText={(text) => this.addValues(text, index)}
/>
);
this.setState({ textInput });
};
//Function to add values into the states
addValues = (text, index) => {
let dataArray = this.state.ingredients;
let checkBool = false;
if (dataArray.length !== 0) {
dataArray.forEach((element) => {
if (element.index === index) {
element.text = text;
checkBool = true;
}
});
}
if (checkBool) {
this.setState({
ingredients: dataArray,
});
} else {
dataArray.push({ text: text, index: index });
this.setState({
ingredients: dataArray,
});
}
};
//function to console the output
getValues = () => {
console.log("Data", this.state.ingredients);
this.props.ingredients = this.state.ingredients;
console.log(this.props.ingredients);
};
render() {
return (
<View>
<View style={styles.icon}>
<View style={{ margin: 10 }}>
<TouchableOpacity>
<Ionicons
name="add"
size={24}
color="black"
onPress={() => this.addTextInput(this.state.textInput.length)}
/>
</TouchableOpacity>
</View>
<View style={{ margin: 10 }}>
<Button title="Remove" onPress={() => this.removeTextInput()} />
</View>
</View>
{this.state.textInput.map((value) => {
return value;
})}
<Button title="Get Values" onPress={() => this.getValues()} />
</View>
);
}
}
export default DishIngredients;

你可以使用React Context

const DishContext = React.createContext({
dish: [],
setDish: () => {},
});
export const useDishContext = () => React.useContext(DishContext);
export const AppDishProvider = ({children}) => {
const [dish, setDish] = useState([{ingredients: []}]);
const defaultDish = {
dish,
setDish,
};
return (
<DishContext.Provider value={defaultDish}>{children}</DishContext.Provider>
);
};

然后

/** Wrap your TabNavigator with AppDishProvider */
<AppDishProvider>
<YourTabNavigator />
</AppDishProvider>

然后

/**
* In DishIngredients, or your TabNavigator...
* You get access to dish-state, and setDish using your
* custom-hook `useDishContext`
*/
const { dish, setDish } = useDishContext();

如果你使用基于类的组件

class DishIngredient extends React.Component {
static contextType = DishContext;
/**
* Current context-value could be accessed by
* `this.context`
*/
render() {
const {dish, setDish} = this.context;
/** .... */
}
}

假设你没有在你的应用程序连接redux…

无需对当前代码做太多更改,就可以这样做

const addIngredient = (ingredient) => {
// TODO: ingredient
};
return (
<Tab.Navigator>
<Tab.Screen name="Ingredient">
{(props) => (
<DishIngredients
{...props}
ingredients={dish}
addIngredient={addIngredient}
/>
)}
</Tab.Screen>
</Tab.Navigator>
);

如您所见,有一个函数addIngredient(您可以根据需要重命名),它将像this.props.addIngredient(<Your Ingredient text>)一样在DishIngredients中作为prop引入。

ReactContext这也是一个不错的解决方案,但我认为,这将迫使你的应用程序重新渲染每次你的上下文变化。这可能会影响你的表现。