Home > other >  How to set a page its state from a React Component?
How to set a page its state from a React Component?

Time:07-18

On a React page I have:

<a
    data-tab="settings"
    onClick={() =>
        this.setState({ active_tab: "settings" })
    }
>
    <i style={{ backgroundImage: "url(/icons/settings.svg)" }} />
    <span>To settings</span>
</a>

How can I convert this to a Component?

On the React page I replaced the above code block with:

import MyButton from "../components/MyButton/";
MyButton({
    tab: "settings",
    icon: "/icons/settings.svg",
    label: "To settings",
})

And I created the Component:

import React from "react";

const MyButton = (props) => {
    const { tab, icon, label } = props;

    return (
        <div className="tab-button">
            <a
                data-tab={tab}
                // next line doesn't work...
                onClick={() =>
                    this.setState({ active_tab: {tab} })
                }
            >
                <i style={{ backgroundImage: `url(${icon})` }} />
                <span> {label} </span>
            </a>
        </div>
    );
};

export default MyButton;

It correctly displays the icon and the label.

But it doesn't change the state of active_tab on the React page. Clicking on the link generates the error _this is undefined.

What am I doing wrong? How can I change the state on the React page from this Component?


Update: I've tried it with a Class setup:

On React page:

import React, { Component, Fragment } from "react";
import MyButton from "../components/MyButton/";

return (
    <Fragment>
        ...
        {
            isAdmin ? (
                <MyButton
                    tab="settings"
                    icon="/icons/settings.svg"
                    label="To settings"
                />
            ) : ("")
        }
        ...
    </Fragment>

Component:

class MyButton extends Component {
    constructor(props) {
        super(props);
        this.state = {
            tab: props.tab,
            icon: props.icon,
            label: props.label,
        };
    }
    render() {
        const { tab, icon, label } = this.state;
        return (
            <div className="tab-button">
                <a
                    data-tab={tab}
                    onClick={() =>
                        this.setState({ active_tab: {tab} })
                    }
                >
                    <i style={{ backgroundImage: `url(${icon})` }} />
                    <span>{label}</span>
                </a>
            </div>
        )
    }
}

export default MyButton;

The result is still the same: the label and icon show up, but clicking on it doesn't work. This time it doesn't generate an error but just nothing happens, meaning the state on the Page hasn't changed.

CodePudding user response:

You can't use this type of states in a function. You need a React component class or use generally React hooks.

So replace

const MyButton = (props) => {

by

class MyButton extends Component {
      constructor(props) {
        super(props);
      }

and use a

render() {return (<div>XXX</div>)}

Then you can use functions like this.setState()

CodePudding user response:

With Functional Components you have to use React Hooks.

Here's a link with an overview: https://reactjs.org/docs/hooks-intro.html

In your case it looks like you just need to use the useState hook to keep track of and change your active_tab state.

Here's How I would do it:

import React from "react";

const MyButton = ({tab, icon, label}) => {
    
    const [tab, setTab] = useState(tab)

    return (
        <div className="tab-button">
            <a
                data-tab={tab}
                // next line doesn't work...
                onClick={() => setTab(tab)}
            >
                <i style={{ backgroundImage: `url(${icon})` }} />
                <span> {label} </span>
            </a>
        </div>
    );
};

The useState calls you see return the current state and a function to change the state.

For example:

const [tab, setTab] = useState(tab)

Here tab is the current state and setTab is a function that takes an argument, in this case a tab, it would then change the current state to whatever was passed in.

Hope that helps some. Let me know :)

  • Related