Как я могу вызвать функцию, которая set устанавливает внешнюю переменную внутри пользовательского компонента в React Native?

#javascript #reactjs #react-hooks

#javascript #reactjs #реагирующие хуки

Вопрос:

Я все еще новичок в React, но по мере того, как я учусь, я пытаюсь создавать повторно используемые компоненты. Я застрял в радиогруппе. У меня есть все, кроме извлечения ключа из компонента в переменную внутри моего обычного кода.

Мой компонент выглядит следующим образом:

 import React, {useState, useEffect} from "react"
import {Text, TouchableOpacity, View} from "react-native"
import PropTypes from "prop-types"

import * as colors from "../defines/js_colors"

import RN_button from "./RN_button"

function RN_radioGroup(props) {
  const [radioSelect, setRadioSelect] = useState("RN_button")
  // useEffect(() => {}, [radioSelect])

  return (
    <View>
      {props.radioGroupList.map((item) => {
        return (
          <View key={item.key}>
            <RN_button
              buttonText={item.label}
              darkBackgroundColor={radioSelect == item.key ? colors.white : "transparent"}
              darkBorderColor={colors.white}
              darkTextFontColor={colors.textLightBlue}
              // onPress = data => setState({ radioSelect });
              onPress={() => {
                setRadioSelect(item.key)
              }}
            />
          </View>
        )
      })}
    </View>
  )
}

RN_radioGroup.propTypes = {
  radioGroupList: PropTypes.array.isRequired,
}

export default RN_radioGroup
 

RN_button — это пользовательский компонент кнопки, но здесь это не имеет большого значения.
radioGroupList — это массив с ключом и меткой, который я передаю в качестве реквизита, а colors содержит определения разных цветов.

 function screen({navigation}) {
  const [radioValue, setRadioValue] = useState("NULL")
  return (
    <View style={styles.container}>
      <View style={styles.container}>
        <RN_radioGroup radioGroupList={arrays.radioGroup1} onPress={radioValue} />
      </View>
    </View>
  )
}
 

Мне нужно использовать выбранное значение ключа, которое находится в радиогруппе снаружи на экране.
Код экрана сокращен до необходимых базовых элементов, но класс radio group в точности соответствует показанному.

Спасибо за любую помощь.

Ответ №1:

Ответ практически на что угодно в react обычно один из двух:

  1. Не изменяйте состояние (здесь неприменимо).
  2. Поднимите состояние (ответ здесь).

Вам нужно сопоставить выбранное значение с общим предком компонента screen and RN_radioGroup screen кажется, что этого будет достаточно, если поместить его в состояние в компоненте.

Не [radioSelect,setRadioSelect] используйте как часть RN_radioGroup состояния, вместо этого передайте его как prop.

Это будет выглядеть примерно так, когда вы передаете prop of selected RN_radioGroup , которому будет присвоено выбранное значение.

 
function screen({navigation}) {
  const [radioValue, setRadioValue] = useState("NULL")
  return (
    <View style={styles.container}>
      <View style={styles.container}>
        <RN_radioGroup radioGroupList={arrays.radioGroup1} selected={radioValue} onPress={setRadioValue} />
      </View>
    </View>
  )
}

// RN_radioGroup

function RN_radioGroup(props) {
  // the selected value, and the update function are now passed in as props 
  const { selected, onPress, radioGroupList } = props;

  return (
    <View>
      {radioGroupList.map((item) => {
        return (
          <View key={item.key}>
            <RN_button
              buttonText={item.label}
              darkBackgroundColor={radioSelect == item.key ? colors.white : "transparent"}
              darkBorderColor={colors.white}
              darkTextFontColor={colors.textLightBlue}
              { /* onPress, call the updater function, which I've also coincidentally named onPress */ }
              onPress={() => onPress(item.key)}
            />
          </View>
        )
      })}
    </View>
  )
}

 

Комментарии:

1. Я понимаю идею, которую вы здесь объясняете, но я понятия не имею, как ее реализовать. Я видел несколько примеров снятия состояния, они выглядят совершенно иначе в моей реализации. Всякий раз, когда я пытаюсь ее реализовать, я получаю сообщение об ошибке, в котором говорится, что я не могу «обновить компонент изнутри функционального блока другого компонента». Не могли бы вы привести мне пример того, что делать внутри класса radio group, или даже просто указать мне на хороший пример, который объясняет этот тип реализации. И спасибо вам за помощь до сих пор.

2. @HeinK кажется, я редактирую, чтобы понять, имеет ли это какой-то смысл.

Ответ №2:

Основная идея заключается в том, что вы поднимаете состояние вверх, что означает, что вы должны указать [radioSelect,setRadioSelect] путь вверх в компоненте, который содержит RN_radioGroup

как-то так

 // my screen
function screen({navigation}) {
  const [radioValue, setRadioValue] = useState("NULL")
  return (
    <View style={styles.container}>
      <View style={styles.container}>
        <RN_radioGroup 
          radioGroupList={arrays.radioGroup1} 
          selected={radioValue} 
          onSelect={setRadioValue} />
      </View>
    </View>
  )
}

// your RN_radioGroup

function RN_radioGroup(props) {
  // you destructure the props to get these values
  // you use these to change the selected value
  const {selected, onSelect} = props;

  return (
    <View>
      {props.radioGroupList.map((item) => {
        return (
          <View key={item.key}>
            <RN_button
              buttonText={item.label}

              // you compare the value if it is selected here
              darkBackgroundColor={selected == item.key ? colors.white : "transparent"}
              darkBorderColor={colors.white}
              darkTextFontColor={colors.textLightBlue}
              onPress={() => {
                onSelect(item.key)
              }}
            />
          </View>
        )
      })}
    </View>
  )
}


 

Комментарии:

1. Спасибо за комментарий. Адам отредактировал свой предыдущий комментарий, и вы оба посоветовали мне то же самое, но я все равно ценю ответ.