react-native-simple-twitter icon indicating copy to clipboard operation
react-native-simple-twitter copied to clipboard

"Invalid hook call" error

Open ycdaskin opened this issue 1 year ago • 4 comments

When i try to run very basic example given in the readme doc, i am facing invalid hook call error.

My code is:

import { useEffect } from "react";
import { Text, View } from "react-native";
import { useTwitter } from "react-native-simple-twitter";

const TwitterSignin = () => {
    
    const { twitter, TWModal, loggedInUser, accessToken } = useTwitter({
        consumerKey: "my key",
        consumerSecret: "my secret",
    });

    const onLoginPress = async () => {
        try {
            await twitter.login();
        } catch (e) {
            console.log(e.errors);
        }
    }
    

    useEffect(() => {
        console.log(loggedInUser)
    }, [loggedInUser, accessToken]);

    return (
        <View>
            <Text onPress={onLoginPress}>login</Text>
            <TWModal />
        </View>
    )
}

export default TwitterSignin
image

react native version: 0.71.6

ycdaskin avatar Apr 20 '23 07:04 ycdaskin

Did you find a way to solve this?

AlbertJohanson avatar Sep 16 '23 00:09 AlbertJohanson

no. i am not using this library anymore. i am not using any libraries tho. i solved it by using twitter rest api. it was a little bit hard to understand at the beginning but now i have a pure js and no dependency solution.

ycdaskin avatar Sep 18 '23 06:09 ycdaskin

@ycdaskin can you please provide the code

Fardeen-Niyazi avatar Sep 27 '23 16:09 Fardeen-Niyazi

const TwitterSignup = ({ navigation }) => {

    const CONSUMER_KEY = 'Your consumer key / api key';
    const CONSUMER_SECRET = 'your consumer secret key / api secret key';
    let ACCESS_TOKEN = ''; // We will use it later
    let ACCESS_TOKEN_SECRET = ''; // We will use it later


    const [loading, setLoading] = useState(false)


    useEffect(() => {
        Linking.addEventListener('url', handleOpenURL);
        return () => Linking.removeEventListener('url', handleOpenURL);
    }, [])

   
    const handleOpenURL = (event) => {
        // You have to set your callback url on your twitter developer account page. It must be a deeplink that redirects to your app. there will be some additional steps for android and ios. yo can find them easly by googling
        handleTwitterCallback(event);
    }

    // these are some helper functions
    const generateNonce = () => {
        return Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
    }

    const generateTimestamp = () => {
        return Math.floor(Date.now() / 1000);
    }

    const generateBaseString = (method, url, params) => {
        const parameterString = Object.keys(params)
            .map((key) => `${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`)
            .join('&');

        return `${method}&${encodeURIComponent(url)}&${encodeURIComponent(parameterString)}`;
    }

    const generateSigningKey = (consumerSecret, tokenSecret) => {
        return `${encodeURIComponent(consumerSecret)}&${encodeURIComponent(tokenSecret)}`;
    }

    const generateOAuthSignature = (baseString, signingKey) => {
        const signature = CryptoJS.HmacSHA1(baseString, signingKey).toString(CryptoJS.enc.Base64);
        return encodeURIComponent(signature);
    }

    const generateAuthorizationHeader = (params) => {
        const headerParams = Object.keys(params)
            .map((key) => `${key}="${params[key]}"`)
            .join(', ');

        return `OAuth ${headerParams}`;
    }

    async function getRequestToken() {
        const requestTokenURL = 'https://api.twitter.com/oauth/request_token';
        const callbackURL = 'yourapp://oauth-callback'; // callback url comes here. it must be something like this example
        const oauthSignatureMethod = 'HMAC-SHA1';
        const oauthVersion = '1.0';

        const oauthNonce = generateNonce();
        const oauthTimestamp = generateTimestamp();

        const oauthParams = {
            oauth_callback: callbackURL,
            oauth_consumer_key: CONSUMER_KEY,
            oauth_nonce: oauthNonce,
            oauth_signature_method: oauthSignatureMethod,
            oauth_timestamp: oauthTimestamp,
            oauth_version: oauthVersion,
        };

        // order OAuth params and sign
        const orderedParams = Object.keys(oauthParams)
            .sort()
            .map((key) => `${encodeURIComponent(key)}=${encodeURIComponent(oauthParams[key])}`)
            .join('&');

        const baseString = `POST&${encodeURIComponent(requestTokenURL)}&${encodeURIComponent(orderedParams)}`;

        const signingKey = `${encodeURIComponent(CONSUMER_SECRET)}&`;

        const oauthSignature = CryptoJS.HmacSHA1(baseString, signingKey).toString(CryptoJS.enc.Base64);

        // create Authorization header 
        const authorizationHeader = `OAuth oauth_callback="${encodeURIComponent(callbackURL)}", oauth_consumer_key="${CONSUMER_KEY}", oauth_nonce="${oauthNonce}", oauth_signature="${encodeURIComponent(oauthSignature)}", oauth_signature_method="${oauthSignatureMethod}", oauth_timestamp="${oauthTimestamp}", oauth_version="${oauthVersion}"`;

        try {
            const response = await axios(requestTokenURL, {
                method: 'POST',
                headers: {
                    Authorization: authorizationHeader
                }
            });
            const responseData = response.data;
            const requestToken = responseData.match(/oauth_token=([^&]+)/)[1];

            // now redirect user to twitter login screen
            const twitterLoginURL = `https://api.twitter.com/oauth/authenticate?oauth_token=${requestToken}`;
            Linking.openURL(twitterLoginURL);
        } catch (error) {
            console.error('Request Token alınamadı:', error);
        }
    }


   

    const handleTwitterCallback = async (event) => {
        const url = event.url;

        const params = url.split('?')[1];
        const tokenParts = params.split('&');
        const requestToken = tokenParts[0].split('=')[1];
        const oauthVerifier = tokenParts[1].split('=')[1];


        const accessTokenURL = 'https://api.twitter.com/oauth/access_token';
        const method = 'POST';
        const oauthNonce = generateNonce();
        const oauthTimestamp = generateTimestamp();
        const oauthSignatureMethod = 'HMAC-SHA1';
        const oauthVersion = '1.0';

        const baseString = generateBaseString(method, accessTokenURL, {
            oauth_consumer_key: CONSUMER_KEY,
            oauth_nonce: oauthNonce,
            oauth_signature_method: oauthSignatureMethod,
            oauth_timestamp: oauthTimestamp,
            oauth_token: requestToken,
            oauth_verifier: oauthVerifier,
            oauth_version: oauthVersion,
        });

        const signingKey = generateSigningKey(CONSUMER_SECRET, '');
        const oauthSignature = generateOAuthSignature(baseString, signingKey);

        const headers = {
            Authorization: generateAuthorizationHeader({
                oauth_consumer_key: CONSUMER_KEY,
                oauth_nonce: oauthNonce,
                oauth_signature: oauthSignature,
                oauth_signature_method: oauthSignatureMethod,
                oauth_timestamp: oauthTimestamp,
                oauth_token: requestToken,
                oauth_verifier: oauthVerifier,
                oauth_version: oauthVersion,
            }),
        };

        try {
            const response = await axios.post(accessTokenURL, null, { headers });
            const responseData = response.data;
            const userAccessToken = responseData.match(/oauth_token=([^&]+)/)[1];
            const userAccessTokenSecret = responseData.match(/oauth_token_secret=([^&]+)/)[1];

            ACCESS_TOKEN = userAccessToken;
            ACCESS_TOKEN_SECRET = userAccessTokenSecret;

            //User authenticatedı, now we can get user information
            const userInfo = await getUserInfo();

            // now we have use user info. we can use it as we want
            console.log('User info:', userInfo);
            

        } catch (error) {
            console.error('Access Token alınamadı:', error);
        }
    }

    const getUserInfo = async () => {
        const verifyCredentialsURL = 'https://api.twitter.com/1.1/account/verify_credentials.json';
        const method = 'GET';
        const oauthNonce = generateNonce();
        const oauthTimestamp = generateTimestamp();
        const oauthSignatureMethod = 'HMAC-SHA1';
        const oauthVersion = '1.0';

        const baseString = generateBaseString(method, verifyCredentialsURL, {
            oauth_consumer_key: CONSUMER_KEY,
            oauth_nonce: oauthNonce,
            oauth_signature_method: oauthSignatureMethod,
            oauth_timestamp: oauthTimestamp,
            oauth_token: ACCESS_TOKEN,
            oauth_version: oauthVersion,
        });

        const signingKey = generateSigningKey(CONSUMER_SECRET, ACCESS_TOKEN_SECRET);
        const oauthSignature = generateOAuthSignature(baseString, signingKey);

        const headers = {
            Authorization: generateAuthorizationHeader({
                oauth_consumer_key: CONSUMER_KEY,
                oauth_nonce: oauthNonce,
                oauth_signature: oauthSignature,
                oauth_signature_method: oauthSignatureMethod,
                oauth_timestamp: oauthTimestamp,
                oauth_token: ACCESS_TOKEN,
                oauth_version: oauthVersion,
            }),
        };

        try {
            const response = await axios.get(verifyCredentialsURL, { headers });

            // you can print entire response.data object to see what information is coming
            const { id, name, screen_name, profile_image_url_https } = response.data;
            return { id, name, screen_name, profile_image_url_https };
        } catch (error) {
            console.error('Kullanıcı bilgileri alınamadı:', error);
        }
    }






    return (
        <SafeAreaView style={{ flex: 1, }}>
            <View
                style={{
                    flex: 1,
                    paddingTop: Platform.OS === "android" ? 20 : 0,
                    padding: 20
                }}
            >
                <Header
                    title={"Twitter Login"}
                    buttonBehavior="back"
                    onBackPress={() => navigation.goBack()}
                    colors={colors}
                />
                <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>

                    <TouchableOpacity
                        style={{
                            ...styles.ssoButton,
                            borderColor: colors.text01
                        }}
                        onPress={getRequestToken}
                        disabled={loading}
                    >
                        <SvgFromXml
                            xml={TwitterIcon}
                        />
                        {loading ? (
                            <ActivityIndicator />
                        ) : (
                            <Text
                                style={{
                                    ...styles.text,
                                    color: colors.text
                                }}
                            >
                                {"Login with Twitter"}
                            </Text>
                        )}

                    </TouchableOpacity>
                </View>
            </View>
        </SafeAreaView>
    );
}


export default TwitterSignup;


const styles = StyleSheet.create({
    ssoButton: {
        flexDirection: 'row',
        height: 56,
        marginRight: 16,
        borderRadius: 28,
        borderWidth: .5,
        alignItems: 'center',
        paddingRight: 20,
        paddingLeft: 20
    },
    text: {
        fontFamily: globalStyles.fontMedium,
        fontSize: 16,
        marginLeft: 8,
    }
})

ycdaskin avatar Sep 28 '23 07:09 ycdaskin