Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 从子级访问useState钩子_Javascript_Reactjs_React Native - Fatal编程技术网

Javascript 从子级访问useState钩子

Javascript 从子级访问useState钩子,javascript,reactjs,react-native,Javascript,Reactjs,React Native,现在,每个子项(SelectorButton)都可以打开和关闭,如果打开,则该组件的标题将添加到父页面上的“当前”数组中,当关闭时,该组件的标题将从数组中弹出。我试图将其设置为,如果“当前”数组中有多个标题(至少按下一个按钮),则“下一步”按钮可见 我现在遇到的问题是,控制按钮内容的if语句总是认为'current.length'==0,这是因为它没有重新加载,它在第一次加载页面时查看的是'current'的初始状态 我非常确定我需要将“当前”设置为useState钩子,但不知道如何将该信息传递

现在,每个子项(SelectorButton)都可以打开和关闭,如果打开,则该组件的标题将添加到父页面上的“当前”数组中,当关闭时,该组件的标题将从数组中弹出。我试图将其设置为,如果“当前”数组中有多个标题(至少按下一个按钮),则“下一步”按钮可见

我现在遇到的问题是,控制按钮内容的if语句总是认为'current.length'==0,这是因为它没有重新加载,它在第一次加载页面时查看的是'current'的初始状态

我非常确定我需要将“当前”设置为useState钩子,但不知道如何将该信息传递到每个组件中,以便更新它。很抱歉,如果这个解释有点难理解,我很乐意回答任何问题。非常感谢您的帮助:)

父页面:

...
import SelectorButton from '../components/selectorButton';
const SignUpOne = ({ navigation }) => {
    //this gets updated as they click or click off a button
    //this hold the current pressed buttons
    //pretty sure this needs to be a state but Im not sure how to
    //pass this into children
    let current = []
    let nextButton

    if (current.length >= 1) {
        //next button is visible
        console.log('is visible')
        nextButton = <TouchableOpacity><Text>Next</Text></TouchableOpacity>
    } else {
        //its not visisble
        console.log('not visible')
        nextButton = <View></View>
    }

    const textFunction = () => {
        console.log(current)
    }

    return (


        <View style={styles.screen}>
            <ScrollView bounces={false}>
                <View style={{ margin: 20, flex: 1 }}>
                    {/*back button */}
                    <View style={{ width: '100%', flexDirection: 'row', justifyContent: 'space-between' }}>
                        <TouchableOpacity onPress={textFunction} style={styles.backButton}>
                            <Text>back</Text>
                        </TouchableOpacity>


                        <View style={styles.backButton}>
                            <Text>hi</Text>
                        </View>
                    </View>
                    <View style={styles.stepNotify}>
                        <Text style={styles.stepText}>Step 1 of 3</Text>
                    </View>

                    <Text style={styles.question}>What are you looking to improve?</Text>

                    {/*this is where the actual buttons are*/}
                    <View style={styles.optionContainer}>

                        {/*top row of buttons */}
                        <View style={{
                            flexDirection: 'row',
                            justifyContent: 'space-between',
                            width: '100%',
                        }}>
                            {/*actual button item */}
                            <SelectorButton array={current} title='Health'>
                                <Text>icon</Text>
                            </SelectorButton>

                            <SelectorButton array={current} title='???'>
                                <Text>icon</Text>
                            </SelectorButton>
                        </View>

                        {/*middle row of buttons */}
                        <View style={styles.rowContainer}>
                            {/*actual button item */}
                            <SelectorButton array={current} title='Relationships'>
                                <Text>icon</Text>
                            </SelectorButton>

                            <SelectorButton array={current} title='Time Allocation'>
                                <Text>icon</Text>
                            </SelectorButton>
                        </View>

                        {/*final row of buttons */}
                        <View style={styles.rowContainer}>
                            {/*actual button item */}
                            <SelectorButton array={current} title='Career'>
                                <Text>icon</Text>
                            </SelectorButton>

                            <SelectorButton array={current} title='Mental Health'>
                                <Text>icon</Text>
                            </SelectorButton>
                        </View>

                    </View>
                </View>
            </ScrollView>
        </View >
    )
}
export default SignUpOne
...
。。。
从“../components/SelectorButton”导入SelectorButton;
const SignUpOne=({navigation})=>{
//当他们单击或单击某个按钮时,会对其进行更新
//这将保持当前按下的按钮
//相当肯定这需要一个状态,但我不知道如何
//把这个传给孩子们
让电流=[]
让我们下一个按钮
如果(当前长度>=1){
//“下一步”按钮可见
console.log('可见')
下一个按钮=下一个
}否则{
//这是不可访问的
console.log('不可见')
下一个按钮=
}
常量文本函数=()=>{
console.log(当前)
}
返回(
{/*后退按钮*/}
返回
你好
第1步,共3步
你希望改进什么?
{/*这是实际按钮所在的位置*/}
{/*按钮的顶行*/}
{/*实际按钮项*/}
偶像
偶像
{/*中间一行按钮*/}
{/*实际按钮项*/}
偶像
偶像
{/*最后一行按钮*/}
{/*实际按钮项*/}
偶像
偶像
)
}
导出默认SignUpOne
...
SelectorButton组件:

...
const SelectorButton = (props) => {
    //remember that it is rendered for each button seperatley
    //when active is == true, we want it to be added to an array,
    //if it is updated to false, we want to remove it from the array,
    //on submit, we want to push the remaining items to the user profile
    const [active, updateActive] = useState(false)
    //this has the

    const updateActiveHandler = () => {
        updateActive(prev => !prev)


        if (active == true) {
            console.log(props.title, 'is off')
            let index = props.array.indexOf(props.title)
            props.array.splice(index, 1)

        } else {
            console.log(props.title, 'is on')
            props.array.push(props.title)
        }
    }

    return (
        <View {...props} >
            {!active &&

                <View style={{ alignItems: 'center' }}>
                    <TouchableOpacity activeOpacity={1} onPress={updateActiveHandler} style={styles.selectionButton}>
                        {props.children}
                    </TouchableOpacity>
                    <Text style={styles.selectionButtonLabel}>{props.title}</Text>
                </View>
            }

            {active &&
                <View style={{ alignItems: 'center' }}>
                    <TouchableOpacity activeOpacity={1} onPress={updateActiveHandler} style={styles.pressedSelectionButton}>
                        {props.children}
                    </TouchableOpacity>
                    <Text style={styles.pressedSelectionLabel}>{props.title}</Text>
                </View>
            }


        </View>
    )
}

export default SelectorButton;
...
。。。
常量选择器按钮=(道具)=>{
//请记住,它是为每个按钮单独渲染的
//当active为==true时,我们希望将其添加到数组中,
//如果更新为false,我们希望将其从数组中删除,
//提交时,我们希望将剩余的项目推送到用户配置文件中
常量[active,updateActive]=useState(false)
//这有
const updateActiveHandler=()=>{
updateActive(prev=>!prev)
如果(活动==真){
console.log(props.title“已关闭”)
让index=props.array.indexOf(props.title)
道具阵列拼接(索引,1)
}否则{
console.log(props.title'is on')
道具.数组.推送(道具.标题)
}
}
返回(
{!激活&&
{props.children}
{props.title}
}
{活动的&&
{props.children}
{props.title}
}
)
}
导出默认选择器按钮;
...
对于更多的上下文,这里是正在呈现的页面,SelectorButton是每个或多个框,当至少按下一个按钮(变为蓝色)时,next按钮显示)还需要确保所有按下的按钮都已存储(在下一个注册步骤中添加到firebase用户配置文件)

是的

const [current, setCurrent] = useState([])

就我所知,这是正确的解决办法。然后简单地将setCurrent函数作为道具传递给必要的子级。之后,您将能够更新子组件的当前值。

就像一些答案已经告诉您的那样,您可以传递setState,实际上您可以传递任何内容

当您有
const[current,setCurrent]=useState(“”)时然后您可以传递current和setCurrent

另一件事是,当您不需要状态,但希望有一个类似于类属性的变量时,最好使用“useRef”:

由let创建的普通变量的问题是,例如,您有一个变量“current”,它用一个空数组初始化,当您将其更改为其他变量,然后当您的组件重新加载时(因为状态已更改),则current将再次用空数组初始化

您可以认为,当您的组件重新渲染时,就像react第一次渲染您的组件一样,唯一的区别是,您的状态现在与第一次渲染时不同。

另外:props.array.pus
const whatever = useRef("");
whatever.current = "new value";
console.log(whatever.current) // new value